home *** CD-ROM | disk | FTP | other *** search
/ The AGA Experience 3 / AGA Experience Volume 3 (1997)(NFA - SAdENESS)[!].iso / software / utilities / misc / atebeta5b / source-code / atebeta5b.c.bak next >
Encoding:
Text File  |  1996-09-08  |  93.4 KB  |  2,876 lines

  1. /* Amiga Type Engine 1.5 (BETA 5)
  2.  
  3.    Perpetrated by OPTIMUS PRIME, AUTOBOT Commander
  4.    (Also known as Gordon Fecyk)
  5.  
  6.    Source is specific for DICE C 3.0 for the Amiga.  Requires
  7.    postlib.h and post.library 1.7 by Adrian Ayward.  Also works
  8.    with HWGPOST.
  9.  
  10.    Additions since 1.0:
  11.    better CharKern handling so weird italic characters don't suffer from tail chop
  12.    use of .AFM files and ATEencoding.ps instead of typeface itself to improve
  13.        rendering speed and character spacing
  14.  
  15.    Additions since 1.2:
  16.    better soft style handling.  I change fonts in the Text() patch now, to
  17.        accomodate stupid programs that don't even try to load styles other than
  18.        the plain style, then SetSoftStyle() them
  19.    AvailFonts() patch to avoid requiring stupid .font files, and an attempt
  20.        to reduce disk access by intercepting AvailFonts() calls with a zero buffer
  21.  
  22.    Additions for 1.3c
  23.    More efficient searches through the fontlist; since the patches do searches,
  24.        why does the mainline need to?
  25.  
  26.    Additions for 1.3d
  27.    Crude CLI detachment via Execute(argv[0], 0, 0) which actually works.
  28.    Minor char chop fixing, but it chops on the other side now. Arrgh.
  29.    Beginning of parameter passing via public message port, facility
  30.        to add more parameters as needed.
  31.    No more breaking via CTRL-C: must type ATE -exit to break.
  32.    Now can run from Workbench!!!!
  33.  
  34.    Additions for 1.4
  35.    Removed all references to callextfunc, so I no longer need several
  36.        functions that the PostScript code uses.
  37.    Began introducing more parameters into parameter handler, introduced
  38.        -trace and -debug.
  39.    Introduced function to rebuild ATE font lists upon adding or removing
  40.        typefaces, and for changing the AvailFonts size options.
  41.    Improved character rendering which takes about 2/3 the original time
  42.        to draw!  FAAAAST!
  43.    Expunge patch for post.library added.  In a low memory panic, ATE will
  44.        free up unused TextFonts and FontNodes.
  45.  
  46.    New for 1.5:
  47.    Modifications for HWG version of post (V22).  This requires post V22
  48.        to operate along with the various extensions for this library.
  49.    Support for ta_DeviceDPI following Commodore's misguided spec
  50.    Support for NewScaledDiskFont() following a slightly better spec
  51.  
  52. */
  53.  
  54. #include <stdio.h>
  55. #include <string.h>
  56. #include <stdarg.h>
  57. #include <exec/types.h>
  58. #include <exec/exec.h>
  59. #include <exec/libraries.h>
  60. #include <clib/exec_protos.h>
  61. #include <dos/dos.h>
  62. #include <graphics/rastport.h>
  63. #include <graphics/text.h>
  64. #include <diskfont/diskfont.h>
  65. #include <clib/utility_protos.h>
  66. #include <utility/tagitem.h>
  67. #include "hwgpostlib.h"
  68.  
  69. /* Set to TRUE for printing PostScript debugging messages */
  70.     BOOL        optTrace;
  71.     BOOL        optDebug;
  72. /* Another BOOL for allowing software styles on ATE fonts */
  73.     BOOL        optSoftStyles;
  74. /* Default density of untagged fonts */
  75.     int        defaultDPI;
  76.  
  77. /* PostScript external data */
  78. struct    Library        *PSbase;        /* Library struct for post.library */
  79. struct    PSparm        *psParm;        /* For some stupid reason this needs */
  80.                         /* to be external.  Thanks Adrian. */
  81.     int        psActivation;        /* Record for PS activation */
  82.     int        psError;        /* Error checking for each PS call */
  83.     char        nameBuffer[100 + 5];    /* Bogus space for PS initalization */
  84.  
  85. /* end of PostScript external data (I hope) */
  86.  
  87. /* External pointers for system patches */
  88. struct    Library        *diskfontBase;
  89. struct    Library        *gfxBase;
  90.  
  91. /* This is an extended diskfont header with two longwords preceeding it.
  92.    This is for the NewScaledDiskFont patch but it will apply to all
  93.    ATE fonts, just to streamline some of the code.  Normal FontNodes
  94.    won't use this extra data. */
  95. struct    ExtDFHeader {
  96.         ULONG        edf_Length;
  97.         ULONG        edf_NextSeg;    /* This will be zero */
  98.     struct    DiskFontHeader    edf_DFHeader;    /* Including TextFont */
  99.     };
  100.  
  101. /* FontNode struct, holds all data specific to a built TextFont */
  102. struct    FontNode {
  103.     /* basic Node struct for searches */
  104.     struct    Node        fn_Node;
  105.     /* format for fn_Name: "%50s / %5d / %2x" for "name / size / style" */
  106.     /* fn_Name is mainly used for node searching */
  107.         char        fn_Name[64];
  108.     /* As of Beta 3B, this is in to prevent re-opening of error-prone fonts */
  109.         BOOL        fn_BlackList;
  110.     /* Set to non-zero if a certain character exists already */
  111.         char        fn_BuiltChars[256];
  112.     /* Data POST uses */
  113.         int        fn_LowChar, fn_HighChar;
  114.         int        fn_OptBaseLine, fn_BaseLine;
  115.         int        fn_NominalWidth, fn_NominalCount;
  116.         char        fn_OptFontEncoding, fn_TypefaceName[64];
  117.         int        fn_MaxFontLength, fn_MaxCharLength;
  118.         int        fn_MaxModulo, fn_MaxWidth, fn_ActWidth;
  119.         int        fn_NomCount, fn_NomWidth;
  120.         int        fn_BaseLength, fn_FontSize;
  121.         UBYTE        fn_Style;
  122.     /* Bounding box & graphic position info */
  123.         int        fn_CharWidths[256];
  124.         int        fn_LowLeftX[256], fn_LowLeftY[256];
  125.         int        fn_UpRightX[256], fn_UpRightY[256];
  126.         int        fn_CharPosX, fn_CharPosY;
  127.     /* XDPI generated from (ta_XDPI / ta_YDPI) * defaultDPI
  128.        as per Commodore spec */
  129.         int        fn_XDPI;
  130.     /* Pointers to data areas in the TextFont struct */
  131.         char        *fn_CharData, *fn_CharFontName;
  132.         short        *fn_CharLoc, *fn_CharSpace, *fn_CharKern;
  133.     /* Heinz says I can use multiple page descriptions now.  Not. */
  134. //    struct    PSdevice    fn_Page;
  135.     /* Ptr to a diskfont header with an 8 byte prefix (Seglist header) */
  136.     struct    ExtDFHeader    *fn_ExtDFHeader;
  137.     /* The TextFont in question */
  138.     struct    TextFont    *fn_TextFont;    /* Within fn_extDFHeader */
  139.     /* the TextFont will soon immediately follow the FontNode struct */
  140.     };
  141.  
  142. /* modes for fn_BuiltChars */
  143. #define    CHAR_NOT_DRAWN    0
  144. #define    CHAR_DRAWN    2
  145. #define    CHAR_NEEDED    1
  146.  
  147. /* ATEFontList struct, contains a Semaphore and the FontList itself */
  148. struct    ATEFontList {
  149.     struct    SignalSemaphore    ateSemaphore;
  150.     struct    List        fontList;
  151.     };
  152.  
  153. /* One external pointer so the patches can search the list */
  154. struct    ATEFontList    *ateFontList;
  155.  
  156. /* Simple fcn that generates an OpenCount of all ATE fonts in use */
  157.     int        CountOpenFonts(void);
  158.  
  159. /* Logic behind ATEAvailFonts struct:
  160.       Stores enough data to build AvailFonts structs for the AvailFonts()
  161.    patch.  PrepAvailFonts() builds this structure from the size max and
  162.    size increment values, and the _ATE_ names fount in FONTS:.
  163.       Because changes can happen anytime, I set aside an external Semaphore
  164.    to protect the ptr to this data, as even the ptr can change at any time.
  165.       TextAttrs use pointers to names, not the names themselves.  So the names
  166.    need to be in that memory space somewhere.  I work around diskfont.library's
  167.    AvailFonts() call by spotting the temporary AvailFontsHeader in the middle
  168.    of the memory pool, then call it with the original parameters, and copy
  169.    the NumEntries value.  Then I add my extra data at the end of where 
  170.    diskfont.library put its extra data, and fill in the beginning of the pool
  171.    with my (T)AvailFonts, NumEntries plus numTAs, then exit. (whew.) 
  172.  
  173.    ***** This is the buggiest part, even though I tested it many times,
  174.    some apps just don't like it. I think the apps are broken. */
  175.  
  176. /* ATEAvailFonts struct, contains needed info for AvailFonts() patch */
  177. struct    ATEAvailFonts {
  178.         int        aaf_SizeDiskFonts;  /* Memory for diskfonts before ATE */
  179.         int        aaf_SizeATEFonts;   /* Memory for all ATE TTextAttrs */
  180.         int        aaf_SizeATEData;    /* Size of fontname & tag data */
  181.     struct    TagItem        aaf_ATETags[2];        /* Taglist for ATE TTextAttrs */
  182.         char        *aaf_FontNames;     /* ptr to start of ATE fontnames */
  183.         int        aaf_NumNames;       /* total all unique ATE fontnames */
  184.         int        aaf_SizeInc;        /* Point size increment */
  185.         int        aaf_SizeMax;        /* Maximum point size */
  186. /*        char        aaf_FontNames[][32];   Start of font names */
  187.     /* memory sizes based on TAvailFonts structures, just to be safe */
  188.     };
  189.  
  190. /* One external pointer for ATEAvailFonts for other processes to see */
  191. struct    ATEAvailFonts    *ateAvailFonts;
  192. /* Semaphore to allow safe access */
  193. struct    SignalSemaphore    aafSemaphore;
  194. /* Here's the fcn that builds this struct.
  195.    diskfont size of zero means hide all Amiga diskfonts */
  196. struct    ATEAvailFonts    *PrepATEAvailFonts(int sizeMax, int sizeInc, int diskfontSize);
  197.  
  198. /* An external for the encoding array */
  199.     char        encodingExternal[256][24];
  200.  
  201. /* Message structures, all based on my extended Message struct ATEMessage */
  202. struct    ATEMessage {
  203.     struct    Message        ate_Message;
  204.         int        ate_MsgLength;
  205.     struct    MsgPort        *ate_DestPort;
  206.     };
  207.  
  208. struct    DiskfontMsg {
  209.     struct    ATEMessage    df_ATEMsg;
  210.     struct    TextAttr    *df_TextAttr;
  211.     struct    FontNode    *df_FontNode;
  212.     struct    TextFont    *df_TextFont;
  213.         BOOL        df_ATEFont;
  214.     };
  215.  
  216. struct    NsdfMsg {
  217.     struct    ATEMessage    nsdf_ATEMsg;
  218.     struct    TextFont    *nsdf_TextFont;
  219.     struct    TextAttr    *nsdf_TextAttr;
  220.     struct    DiskFontHeader    *nsdf_DFHeader;
  221.     };
  222.  
  223. struct    TextMsg {
  224.     struct    ATEMessage    tm_ATEMsg;
  225.     struct    RastPort    *tm_RastPort;
  226.     struct    FontNode    *tm_FontNode;
  227.         STRPTR        tm_Chars;
  228.         WORD        tm_Length;
  229.         BOOL        tm_ATEFont;
  230.     };
  231.  
  232. struct    SSStyleMsg {
  233.     struct    ATEMessage    ss_ATEMsg;
  234.     struct    RastPort    *ss_RastPort;
  235.         ULONG        ss_NewStyle;
  236.         ULONG        ss_Enable;
  237.     struct    TextFont    *ss_ChangedFont;
  238.     struct    FontNode    *ss_FontNode;
  239.         ULONG        ss_SoftStyleNeeded;
  240.         BOOL        ss_ATEFont;
  241.     };
  242.  
  243. struct    CommandMsg {
  244.     struct    ATEMessage    cm_ATEMsg;
  245.         int        cm_ArgC;
  246.         char        **cm_ArgV;
  247.         BOOL        cm_Result;
  248.     };
  249.  
  250. /* Ptrs to MsgPorts internal to ATE */
  251. struct    MsgPort        *ateODFPort, *ateTextPort, *ateSSSPort, *ateNSDFPort;
  252.  
  253. /* Signal info for the Expunge() patch, for this task
  254.    and the allocated signal */
  255. struct    Task        *ateMainTask;
  256.     BYTE        ateDfeSigBit;
  257.  
  258. /* Prototypes of system patches and original functions */
  259. __geta4 __regargs struct TextFont    *NewOpenDiskFont(__A0 struct TextAttr *textAttr, __A6 struct Library *libBase);
  260. __geta4          struct TextFont    *(*OldOpenDiskFont)(__A0 struct TextAttr *textAttr, __A6 struct Library *libBase);
  261. __geta4    __regargs     void        NewText(__A1 struct RastPort *rastPort, __A0 STRPTR textString, __D0 WORD length, __A6 struct Library *libBase);
  262. __geta4               void        (*OldText)(__A1 struct RastPort *rastPort, __A0 STRPTR textString, __D0 WORD length, __A6 struct Library *libBase);
  263. __geta4    __regargs     ULONG        NewSSStyle(__A1 struct RastPort *rastPort, __D0 ULONG newStyle, __D1 ULONG enable, __A6 struct Library *libBase);
  264. __geta4             ULONG        (*OldSSStyle)(__A1 struct RastPort *rastPort, __D0 ULONG newStyle, __D1 ULONG enable, __A6 struct Library *libBase);
  265. __geta4 __regargs     LONG        NewAvailFonts(__A0 struct AvailFontsHeader *afhBuffer, __D0 LONG afBufSize, __D1 ULONG afFlags, __A6 struct Library *libBase);
  266. __geta4             LONG        (*OldAvailFonts)(__A0 struct AvailFontsHeader *afhBuffer, __D0 LONG afBufSize, __D1 ULONG afFlags, __A6 struct Library *libBase);
  267. __geta4    __regargs     ULONG        NewDFbaseExpunge(__A6 struct Library *libBase);
  268. __geta4             ULONG        (*OldDFbaseExpunge)(__A6 struct Library *libBase);
  269. __geta4 __regargs struct DiskFontHeader *NewNSDF(__A0 struct TextFont *tf, __A1 struct TextAttr *ta, __A6 struct Library *libBase);
  270. __geta4          struct DiskFontHeader *(*OldNSDF)(__A0 struct TextFont *tf, __A1 struct TextAttr *ta, __A6 struct Library *libBase);
  271.  
  272. /* These were a misguided attempt to work around a bug in Deluxe Video III */
  273. //__geta4 __regargs     WORD        NewTextLength(__A1 struct RastPort *rastPort, __A0 STRPTR aString, __D0 WORD strCount, __A6 struct Library *libBase);
  274. //__geta4         WORD        (*OldTextLength)(__A1 struct RastPort *rastPort, __A0 STRPTR aString, __D0 WORD strCount, __A6 struct Library *libBase);
  275. //__geta4 __regargs struct TextExtent    *NewTextExtent(__A1 struct RastPort *rastPort, __A0 STRPTR aString, __D0 WORD strCount, __A2 struct TextExtent *te);
  276. //__geta4        struct TextExtent    *(*OldTextExtent)(__A1 struct RastPort *rastPort, __A0 STRPTR aString, __D0 WORD strCount, __A2 struct TextExtent *te, __A6 struct Library *libBase);
  277.  
  278. /* Message sender for the above patches */
  279.              BOOL        ATESendMsg(struct ATEMessage *ateMsg);
  280.  
  281. /* A couple of dead functions not in here anymore */
  282. //          struct FontNode    *SwapSoftStyle(struct RastPort *rp);
  283. //             void        UndoSwapSoftStyle(struct RastPort *rp, struct TextFont *tf, UBYTE softStyle);
  284.  
  285. /* Functions for the PostScript interface and tracing */
  286.     void        PSTrace(char *format, ...);
  287.     void        PSIntf(char *format, ...);
  288.  
  289. /* Functions to simplify some loops, these do most of the PostScript gruntwork */
  290. struct    TextFont    *MakeATEFont(struct FontNode *fontNode, struct TextAttr *textAttr);
  291.     BOOL        MakeATEChars(struct FontNode *fontNode);
  292.  
  293. /* Functions from older versions of ATEServer (with a new one: AddATEStyle) */
  294.     void        chkabort(void) { return; };    /* Kill CTRL-C handler */
  295.     void        ClearFontNames(struct List *fontList);
  296.     BOOL        AddATEFont(struct List *fontList, struct DiskfontMsg *diskfontMsg);
  297.     BOOL        AddATEStyle(struct List *fontList, struct SSStyleMsg *sssMsg);
  298.     BOOL        AddATEChars(struct List *fontList, struct TextMsg *textMsg);
  299. struct    DiskFontHeader    *BuildScaledDiskFont(struct TextFont *textFont, struct TextAttr *textAttr);
  300.     void        ClearUnusedATEFonts(struct FontList *fontList);
  301.  
  302. /* One fcn which is the main process */
  303.     int        ATEmain(struct Task *callingTask, BYTE okSigBit, BYTE failSigBit);
  304.  
  305. /* external file handle for ATE output */
  306.     FILE        *ateOutput;
  307.  
  308. /* wbmain() entry point, supposed to read tooltypes and start ATE 
  309.    with tooltypes options.  In future will include a user interface
  310.    and perhaps become a commodity */
  311.  
  312. int wbmain(struct WBStartup *wbMsg)
  313. {
  314. struct    MsgPort        *ateCmdPort;
  315.     char        *ateCmdPortName = "ATE_Cmd_Port";
  316.     int        exitCode;
  317.     char        *argv[2];
  318. struct    CommandMsg    *ateCmdMsg;
  319.     BOOL        ateStartSuccess;
  320.  
  321.     /* Ok, this makes one VERY BIG assumption that the msgport won't go away
  322.        after I find it.  This makes sense because the only way you can
  323.        break ATE is to send an exit message to it. */
  324.     Forbid();
  325.     ateCmdPort = FindPort(ateCmdPortName);
  326.     Permit();
  327.     
  328.     if (ateCmdPort == 0)
  329.     {
  330.         /* Since this was run from Workbench or WBStartup, I can run
  331.            ATE without having to detach from anything. */
  332.         ateOutput = fopen("CON:0/0/600/75/ATE Message/AUTO/WAIT", "w");
  333.         if (ateOutput != 0)
  334.         {
  335. //            fprintf(ateOutput, "Starting ATE... when you see ATE Ready you can close this window.\n");
  336. //            fprintf(ateOutput, "Double-click this icon again to exit ATE.\n");
  337.             fflush(ateOutput);
  338.             exitCode = ATEmain(0, 0, 0);
  339.             /* This will immediately exit upon returning from ATEmain() */
  340.             fclose(ateOutput);
  341.             return(exitCode);
  342.         }
  343.     }
  344.     else
  345.     {
  346.         /* Send -exit parameter to ATE, but first build the thing */
  347.         ateCmdMsg = (struct CommandMsg *)AllocVec(sizeof(struct CommandMsg) + 64, MEMF_PUBLIC | MEMF_CLEAR);
  348.         if (ateCmdMsg != 0)
  349.         {
  350.             argv[0] = (char *)&ateCmdMsg[1];
  351.             argv[1] = argv[0] + 32;
  352.             strcpy(argv[1], "-exit");
  353.             strcpy(argv[0], "ATEbeta5");
  354.             ateCmdMsg->cm_ATEMsg.ate_MsgLength = sizeof(struct CommandMsg);
  355.             ateCmdMsg->cm_ATEMsg.ate_DestPort = ateCmdPort;
  356.             ateCmdMsg->cm_ArgC = 2;
  357.             ateCmdMsg->cm_ArgV = argv;
  358.             ateStartSuccess = ATESendMsg((struct ATEMessage *)ateCmdMsg);
  359.             if (ateStartSuccess == FALSE)
  360.                 exitCode = 20;
  361.             else
  362.                 exitCode = 0;
  363.             FreeVec(ateCmdMsg);
  364.         }
  365.     }
  366.     return(exitCode);
  367. }
  368.  
  369. /* command line entry point, looks for an existing port and passes
  370.    arguments to it, otherwise it starts the ATE mainline */
  371.  
  372. int main(int argc, char *argv[])
  373. {
  374. struct    MsgPort        *ateCmdPort;
  375. struct    CommandMsg    *ateCmdMsg;
  376.     char        *ateCmdPortName = "ATE_Cmd_Port";
  377.     char        startAteCmdLine[80];
  378.     BOOL        ateStartSuccess;
  379.     int        exitCode = 0;
  380. struct    Task        *callingTask = (struct Task *)0;
  381.     BYTE        okSigBit, failSigBit;
  382.     ULONG        okSig, failSig, signal;
  383.  
  384.     /* Ok, this makes one VERY BIG assumption that the msgport won't go away
  385.        after I find it.  This makes sense because the only way you can
  386.        break ATE is to send an exit message to it. */
  387.     Forbid();
  388.     ateCmdPort = FindPort(ateCmdPortName);
  389.     Permit();
  390.     
  391.     if (ateCmdPort == 0)
  392.     {
  393.         /* Check for "-start" parameter, if so, call ATEmain() */
  394.         if (argc > 1)
  395.         {
  396.             if (strcmp(argv[1], "-start") == 0)
  397.             {
  398.                 ateOutput = fopen("CON:0/0/600/75/ATE Message/AUTO/WAIT", "w");
  399.                 if (ateOutput != 0)
  400.                 {
  401.                     callingTask = (struct Task *)atoi(argv[2]);
  402.                     okSigBit = (BYTE)atoi(argv[3]);
  403.                     failSigBit = (BYTE)atoi(argv[4]);
  404.                     exitCode = ATEmain(callingTask, okSigBit, failSigBit);
  405.                     /* This will immediately exit upon returning from ATEmain() */
  406.                     fclose(ateOutput);
  407.                     return(exitCode);
  408.                 }
  409.             }
  410.         }
  411.         /* No message port found, send command with "-start" parameter */
  412.         callingTask = FindTask(0);
  413.         okSigBit = AllocSignal(-1);
  414.         failSigBit = AllocSignal(-1);
  415.  
  416.         sprintf(startAteCmdLine, "Run >nil: <nil: %s -start %d %d %d",
  417.             argv[0], callingTask, okSigBit, failSigBit);
  418.  
  419.         ateStartSuccess = Execute(startAteCmdLine, 0, 0);
  420.         if (ateStartSuccess == FALSE)
  421.             exitCode = 20;
  422.         else
  423.         {
  424.             printf("ATE started... type %s -exit to terminate ATE.\n", argv[0]);
  425.             printf("Amiga Typeface Engine BETA 1.5\n");
  426.  
  427.             /* Now wait on the signals then send parameters */
  428.  
  429.             okSig = 1 << okSigBit;
  430.             failSig = 1 << failSigBit;
  431.             signal = Wait(okSig | failSig);
  432.  
  433.             if (signal & okSig)
  434.             {
  435.                 exitCode = 0;
  436.                 /* Obtain the new port ptr now */
  437.                 Forbid();
  438.                 ateCmdPort = FindPort(ateCmdPortName);
  439.                 Permit();
  440.             }
  441.             else
  442.                 exitCode = 20;
  443.             FreeSignal(okSigBit);
  444.             FreeSignal(failSigBit);
  445.         }
  446.     }
  447.     if (argc > 1 && exitCode == 0)
  448.     {
  449.         /* There's an active ATE now running, pass parameters to it */
  450.         ateCmdMsg = (struct CommandMsg *)AllocVec(sizeof(struct CommandMsg), MEMF_PUBLIC | MEMF_CLEAR);
  451.         if (ateCmdMsg != 0 && ateCmdPort != 0)
  452.         {
  453.             ateCmdMsg->cm_ATEMsg.ate_MsgLength = sizeof(struct CommandMsg);
  454.             ateCmdMsg->cm_ATEMsg.ate_DestPort = ateCmdPort;
  455.             ateCmdMsg->cm_ArgC = argc;
  456.             ateCmdMsg->cm_ArgV = argv;
  457.             ateStartSuccess = ATESendMsg((struct ATEMessage *)ateCmdMsg);
  458.             if (ateStartSuccess == FALSE)
  459.             {
  460.                 printf("No active ATE to send messages to...\n");
  461.                 exitCode = 20;
  462.             }
  463.             else
  464.             {
  465.                 printf("Updated parameters sent OK\n");
  466.                 exitCode = 0;
  467.             }
  468.             FreeVec(ateCmdMsg);
  469.         }
  470.         else
  471.         {
  472.             if (ateCmdMsg == 0)
  473.                 printf("Not enough memory to send any messages\n");
  474.             if (ateCmdPort == 0)
  475.                 printf("No active ATE to send messages to.\n");
  476.             ateStartSuccess = FALSE;
  477.             exitCode = 20;
  478.         }
  479.     }
  480.     else if (callingTask == 0)
  481.     {
  482.         printf(    "ATE Beta 5 already active\n"
  483.             "Usage: %s -arguments\n"
  484.             "================================\n"
  485.             "-(no)trace          Hide or Show trace messages in code, default NO\n"
  486.             "-(no)debug          Hide or Show all PS commands executed, default NO\n"
  487.             "-hidediskfonts      Show only loaded fonts and ATE fonts to apps\n"
  488.             "-showdiskfonts      Show all Amiga and ATE fonts to apps (default)\n"
  489.             "-softstyleson       Enable algorithmic styles on ATE fonts\n"
  490.             "-softstylesoff      Disable algorithmic styles on ATE fonts (default)\n"
  491.             "-availfonts SM SI   Show what sizes of ATE fonts appear in lists\n"
  492.             "                    SM = size maximum, SI = size increment\n"
  493.             "                    72 and 6 default, shows sizes\n"
  494.             "                    6 12 18 24 30 36 42 48 54 60 66 72\n"
  495.             "-dpi DPI            Change display resolution of ATE fonts\n"
  496.             "                    DPI = dots per inch on screen.  Default 72\n"
  497.             "                    Must close all apps using ATE before using -dpi\n"
  498.             "-exit               Unloads all ATE fonts and exits ATE\n"
  499.             "                    Must close all apps using ATE before using -exit\n"
  500.             "================================\n"
  501.             "You can use many arguments on the same command line.\n"
  502.             "All arguments work in startup as well.\n", argv[0]);
  503.         exitCode = 0;
  504.     }
  505.     return(exitCode);
  506. }
  507.  
  508. /* Mainline of code */
  509. int ATEmain(struct Task *callingTask, BYTE okSigBit, BYTE failSigBit)
  510. {
  511.     APTR        oldFuncPtr, newFuncPtr = &NewOpenDiskFont;
  512.     APTR        oldTextPtr, newTextPtr = &NewText;
  513.     APTR        oldSSSPtr, newSSSPtr = &NewSSStyle;
  514.     APTR        oldAFPtr, newAFPtr = &NewAvailFonts;
  515.     APTR        oldDFEPtr, newDFEPtr = &NewDFbaseExpunge;
  516.     APTR        oldNSDFPtr, newNSDFPtr = &NewNSDF;
  517. //    APTR        oldTLPtr, newTLPtr = &NewTextLength;
  518. //    APTR        oldTEPtr, newTEPtr = &NewTextExtent;
  519.     char        *versionInfo = "$VER:  AmigaTypeEngine_BETA 1.5 (13.8.95)";
  520.     char        *moreInfo = "Written by Gordon Fecyk of Winnipeg / Calgary / Vancouver :)";
  521. struct    MsgPort        *ateCmdPort;
  522. struct    CommandMsg    *commandMsg;
  523. struct    List        *fontList;
  524. struct    SignalSemaphore    *ateSemaphore, *nafSemaphore = &aafSemaphore;
  525. struct    DiskfontMsg    *diskfontMsg;
  526. struct    TextMsg        *textMsg;
  527. struct    SSStyleMsg    *sssMsg;
  528. struct    NsdfMsg        *nsdfMsg;
  529.     ULONG        signal, odfSig, textSig, sssSig, cmdSig, dfeSig, nsdfSig;
  530.     BOOL        keepGoing = TRUE;
  531.     FILE        *encodingFile, *nilInput;
  532.     int        index, asciiValue, openCount, diskfontSize;
  533.     char        readLine[100], charName[32];
  534.  
  535.     optTrace = FALSE;
  536.     optDebug = FALSE;
  537.     optSoftStyles = FALSE;
  538.     defaultDPI = 72;
  539.     /* Do as much allocating as practical then check for failures */
  540.         /* Message ports */
  541.     ateODFPort = CreateMsgPort();
  542.     ateTextPort = CreateMsgPort();
  543.     ateSSSPort = CreateMsgPort();
  544.     ateCmdPort = CreateMsgPort();
  545.     ateNSDFPort = CreateMsgPort();
  546.     ateDfeSigBit = AllocSignal(-1);
  547.         /* ATE font list */
  548.     ateFontList = (struct ATEFontList *)AllocVec(sizeof(struct ATEFontList), MEMF_PUBLIC | MEMF_CLEAR);
  549.         /* post.library (minimum V15) */
  550.     PSbase = OpenLibrary("post.library", 15L);
  551.         /* graphics and diskfont libraries (mininum V36) */
  552.     diskfontBase = OpenLibrary("diskfont.library", 36L);
  553.     gfxBase = OpenLibrary("graphics.library", 36L);
  554.     diskfontSize = AvailFonts(readLine, 0, AFF_DISK | AFF_TAGGED);
  555.     ateAvailFonts = PrepATEAvailFonts(72, 6, diskfontSize);
  556.     psParm = (struct PSparm *)AllocVec(sizeof(struct PSparm), MEMF_PUBLIC | MEMF_CLEAR);
  557.  
  558.     /* check for failures */
  559.     if (ateODFPort == 0 || ateTextPort == 0 || ateSSSPort == 0 || ateCmdPort == 0
  560.     || PSbase == 0 || gfxBase == 0 || diskfontBase == 0 || ateDfeSigBit == -1
  561.     || ateFontList == 0 || ateAvailFonts == 0 || psParm == 0 || ateNSDFPort == 0)
  562.     {
  563.         if (ateNSDFPort != 0)
  564.             DeleteMsgPort(ateNSDFPort);
  565.         else
  566.             fprintf(ateOutput, "Error allocatine one message port\n");
  567.         if (psParm != 0)
  568.             FreeVec(psParm);
  569.         else
  570.             fprintf(ateOutput, "Error allocating RAM for PS struct \n");
  571.         if (ateDfeSigBit != -1)
  572.             FreeSignal(ateDfeSigBit);
  573.         else
  574.             fprintf(ateOutput, "Error obtaining a signal bit\n");
  575.         if (ateCmdPort != 0)
  576.             DeleteMsgPort(ateCmdPort);
  577.         else
  578.             fprintf(ateOutput, "Error opening command port\n");
  579.         if (ateAvailFonts != 0)
  580.             FreeVec(ateAvailFonts);
  581.         else
  582.             fprintf(ateOutput, "Error obtaining memory for ATEAvailFonts\n");
  583.         if (ateSSSPort != 0)
  584.             DeleteMsgPort(ateSSSPort);
  585.         else
  586.             fprintf(ateOutput, "Error opening one message port\n");
  587.         if (ateODFPort != 0)
  588.             DeleteMsgPort(ateODFPort);
  589.         else
  590.             fprintf(ateOutput, "Error opening one message port\n");
  591.         if (ateTextPort != 0)
  592.             DeleteMsgPort(ateTextPort);
  593.         else
  594.             fprintf(ateOutput, "Error opening one message port\n");
  595.         if (PSbase != 0)
  596.             CloseLibrary(PSbase);
  597.         else
  598.             fprintf(ateOutput, "Error opening post.library\n"
  599.                            "You require V15 post.library\n");
  600.         if (ateFontList != 0)
  601.             FreeVec(ateFontList);
  602.         else
  603.             fprintf(ateOutput, "Error allocating RAM for fontList\n");
  604.         if (gfxBase != 0)
  605.             CloseLibrary(gfxBase);
  606.         else
  607.             fprintf(ateOutput, "Error opening graphics.library\n");
  608.         if (diskfontBase != 0)
  609.             CloseLibrary(diskfontBase);
  610.         else
  611.             fprintf(ateOutput, "Error opening diskfont.library\n"
  612.                        "This requires at least WB 2.04\n");
  613.         if (callingTask != 0)
  614.             Signal(callingTask, 1 << failSigBit);
  615.         return(20);
  616.     }
  617.  
  618.     /* initalize the PostScript activation */
  619.     PSTrace("%%Initalizing PostScript Activation\n");
  620.     psParm->page.buf[0] = nameBuffer;
  621.     psParm->page.len = 100;
  622.     psParm->page.depth = 1;
  623.     psParm->page.xbytes = 10;
  624.     psParm->page.xsize = 80;
  625.     psParm->page.ysize = 10;
  626.     psParm->page.xden = 72;
  627.     psParm->page.yden = 72;
  628.     psParm->page.ydir = -1;
  629.     psParm->memvlen = 20000;
  630.     psParm->memflen = 10000;
  631.     psParm->memllen = defmemllen;
  632.     psParm->memhlen = minmemhlen;
  633.     /* This must be a real file handle (IE: "NIL:" in Beta 5) */
  634.     nilInput = fopen("nil:", "r");
  635.     psParm->infh = fdtofh(nilInput);
  636.     psParm->outfh = fdtofh(ateOutput);
  637.     psParm->errfh = fdtofh(ateOutput);
  638.     /* I'm getting lazy... I like MEMF_CLEAR... :) */
  639.  
  640.     psActivation = PScreateact(psParm);
  641.     if (psActivation <= errmax)
  642.     {
  643.         fprintf(ateOutput, "PostScript activation failed\n");
  644.         DeleteMsgPort(ateNSDFPort);
  645.         DeleteMsgPort(ateODFPort);
  646.         DeleteMsgPort(ateTextPort);
  647.         DeleteMsgPort(ateSSSPort);
  648.         DeleteMsgPort(ateCmdPort);
  649.         FreeSignal(ateDfeSigBit);
  650.         FreeVec(psParm);
  651.         FreeVec(ateFontList);
  652.         FreeVec(ateAvailFonts);
  653.         CloseLibrary(PSbase);
  654.         CloseLibrary(gfxBase);
  655.         CloseLibrary(diskfontBase);
  656.         if (callingTask != 0)
  657.             Signal(callingTask, 1 << failSigBit);
  658.         return(20);
  659.     }
  660.  
  661.     /* Run ATE startup files */
  662.     PSTrace("%%All initalization passed, running PS startup & encoding files\n");
  663.     PSIntf("(%.100s) run clear\n", "PSFonts:init.ps");
  664.     if (psError != 0)
  665.     {
  666.         fprintf(ateOutput, "Error running initalization file,\n"
  667.                     "check your PSFonts:init.ps file.\n");
  668.     }
  669.  
  670.     PSIntf("/encoding StandardEncoding 256 array copy def\n");
  671.     PSIntf("[ (%.100s) run] aload length 2 idiv\n", "PSFonts:ATEencoding.ps");
  672.     PSIntf("{ encoding 3 1 roll put } repeat\n");
  673.     PSIntf("/cstr 1 string def\n");
  674.     if (psError != 0)
  675.     {
  676.         fprintf(ateOutput, "Error running initalization file,\n"
  677.                    "check your PSFonts:ATEencoding.ps file.\n");
  678.     }
  679.  
  680.     /* Read encoding file into memory */
  681.     encodingFile = fopen("PSFonts:ATEencoding.ps", "r");
  682.     if (encodingFile != 0)
  683.     {
  684.         while (!feof(encodingFile))
  685.         {
  686.             asciiValue = 0;
  687.             charName[0] = 0;
  688.             readLine[0] = 0;
  689.             fgets(readLine, 100, encodingFile);
  690.             sscanf(readLine, "%3d /%s\n", &asciiValue, charName);
  691.             if (asciiValue != 0)
  692.             {
  693.                 strcpy(encodingExternal[asciiValue], charName);
  694.             }
  695.         }
  696.     }
  697.     if (psError != 0 || encodingFile == 0)
  698.     {
  699.         fprintf(ateOutput, "Cannot parse ATEencoding.ps file\n");
  700.         if (encodingFile != 0)
  701.             fclose(encodingFile);
  702.         DeleteMsgPort(ateNSDFPort);
  703.         DeleteMsgPort(ateODFPort);
  704.         DeleteMsgPort(ateTextPort);
  705.         DeleteMsgPort(ateSSSPort);
  706.         DeleteMsgPort(ateCmdPort);
  707.         FreeSignal(ateDfeSigBit);
  708.         FreeVec(psParm);
  709.         FreeVec(ateFontList);
  710.         FreeVec(ateAvailFonts);
  711.         CloseLibrary(PSbase);
  712.         CloseLibrary(gfxBase);
  713.         CloseLibrary(diskfontBase);
  714.         if (callingTask != 0)
  715.             Signal(callingTask, 1 << failSigBit);
  716.         return(20);
  717.     }
  718.     fclose(encodingFile);
  719.  
  720. //    fprintf(ateOutput, "Number of unique typefaces %d\n", ateAvailFonts->aaf_NumNames);
  721.  
  722.     /* Setup ports */
  723.     odfSig = 1 << ateODFPort->mp_SigBit;
  724.     textSig = 1 << ateTextPort->mp_SigBit;
  725.     sssSig = 1 << ateSSSPort->mp_SigBit;
  726.     cmdSig = 1 << ateCmdPort->mp_SigBit;
  727.     nsdfSig = 1 << ateNSDFPort->mp_SigBit;
  728.     dfeSig = 1 << ateDfeSigBit;
  729.     ateODFPort->mp_Node.ln_Pri = 0;
  730.     ateTextPort->mp_Node.ln_Pri = 0;
  731.     ateSSSPort->mp_Node.ln_Pri = 0;
  732.     ateCmdPort->mp_Node.ln_Pri = 0;
  733.     ateNSDFPort->mp_Node.ln_Pri = 0;
  734.     ateCmdPort->mp_Node.ln_Name = "ATE_Cmd_Port";
  735.     AddPort(ateCmdPort);
  736.     /* prepare list */
  737.     fontList = &ateFontList->fontList;
  738.     fontList->lh_Type = NT_USER;
  739.     NewList(fontList);
  740.     /* Prepare semaphores */
  741.     ateSemaphore = &ateFontList->ateSemaphore;
  742.     InitSemaphore(ateSemaphore);
  743.     InitSemaphore(nafSemaphore);
  744. //    fprintf(ateOutput, "ATE BETA 1.5 ready.\n");
  745.     fflush(ateOutput);
  746.     /* Grab the task ptr for the DFE signals */
  747.     ateMainTask = FindTask(0);
  748.  
  749.     /* Perform patches */
  750.     Forbid();
  751.     oldFuncPtr = SetFunction(diskfontBase, -0x1E, newFuncPtr);
  752.     OldOpenDiskFont = oldFuncPtr;
  753.     oldTextPtr = SetFunction(gfxBase, -0x3C, newTextPtr);
  754.     OldText = oldTextPtr;
  755.     oldSSSPtr = SetFunction(gfxBase, -0x5A, newSSSPtr);
  756.     OldSSStyle = oldSSSPtr;
  757.     oldAFPtr = SetFunction(diskfontBase, -0x24, newAFPtr);
  758.     OldAvailFonts = oldAFPtr;
  759.     oldDFEPtr = SetFunction(diskfontBase, -0x12, newDFEPtr);
  760.     OldDFbaseExpunge = oldDFEPtr;
  761.     oldNSDFPtr = SetFunction(diskfontBase, -0x36, newNSDFPtr);
  762.     OldNSDF = oldNSDFPtr;
  763. //    oldTLPtr = SetFunction(gfxBase, -0x36, newTLPtr);
  764. //    OldTextLength = oldTLPtr;
  765. //    oldTEPtr = SetFunction(gfxBase, -0x2B2, newTEPtr);
  766. //    OldTextExtent = oldTEPtr;
  767.     Permit();
  768.     /* I got the offsets from the included pragmas files. */
  769.  
  770.     /* Signal the calling process we're ready */
  771.     if (callingTask != 0)
  772.         Signal(callingTask, 1 << okSigBit);
  773.  
  774.     /* Begin main process loop */
  775.     for (;;)
  776.     {
  777.         signal = Wait (textSig | odfSig | sssSig | dfeSig | cmdSig | nsdfSig);
  778.  
  779.         if ((signal & cmdSig))
  780.         {
  781.             /* Someone sent a command here. */
  782.             while (commandMsg = (struct CommandMsg *)GetMsg(ateCmdPort))
  783.             {
  784.                 if (commandMsg->cm_ArgC <= 1)
  785.                 {
  786.                     fprintf(ateOutput, "No parameters sent with command \n");
  787.                 }
  788.                 /* Several if() statements happen here for each parameter */
  789.                 else for (index = 1; index < commandMsg->cm_ArgC; index++)
  790.                 {
  791.                     if (strcmp(commandMsg->cm_ArgV[index], "-exit") == 0)
  792.                     {
  793.                         keepGoing = FALSE;
  794.                         break;
  795.                     }
  796.                     /* More if () statements for each argument
  797.                        happen here, and mods happen accordingly */
  798.                     if (strcmp(commandMsg->cm_ArgV[index], "-trace") == 0)
  799.                         optTrace = TRUE;
  800.                     if (strcmp(commandMsg->cm_ArgV[index], "-notrace") == 0)
  801.                         optTrace = FALSE;
  802.                     if (strcmp(commandMsg->cm_ArgV[index], "-debug") == 0)
  803.                         optDebug = TRUE;
  804.                     if (strcmp(commandMsg->cm_ArgV[index], "-nodebug") == 0)
  805.                         optDebug = FALSE;
  806.                     if (strcmp(commandMsg->cm_ArgV[index], "-availfonts") == 0)
  807.                     {
  808.                         /* Make sure these are valid parameters */
  809.                         int    sizeMax, sizeInc, mySizeDiskFonts;
  810.  
  811.                         index++;
  812.                         if (index < commandMsg->cm_ArgC)
  813.                             sizeMax = atoi(commandMsg->cm_ArgV[index]);
  814.                         else
  815.                             sizeMax = 0;
  816.                         index++;
  817.                         if (index < commandMsg->cm_ArgC)
  818.                             sizeInc = atoi(commandMsg->cm_ArgV[index]);
  819.                         else
  820.                             sizeInc = 0;
  821.  
  822.                         if (sizeMax > sizeInc && sizeInc > 0)
  823.                         {
  824.                             /* make the call */
  825.                             ObtainSemaphore(nafSemaphore);
  826.                             mySizeDiskFonts = ateAvailFonts->aaf_SizeDiskFonts;
  827.                             FreeVec(ateAvailFonts);
  828.                             ateAvailFonts = 0;
  829.                             ateAvailFonts = PrepATEAvailFonts(sizeMax, sizeInc, mySizeDiskFonts);
  830.                             if (ateAvailFonts == 0)
  831.                             {
  832.                                 fprintf(ateOutput, "Warning: System extremely low on memory\n");
  833.                                 fflush(ateOutput);
  834.                                 keepGoing = FALSE;
  835.                             }
  836.                             ReleaseSemaphore(nafSemaphore);
  837.                         }
  838.                         else
  839.                         {
  840.                             fprintf(ateOutput, "Usage for -availfonts:\n"
  841.                                        "-availfonts sizemax sizeinc\n");
  842.                             fflush(ateOutput);
  843.                         }
  844.                     }
  845.                     if (strcmp(commandMsg->cm_ArgV[index], "-dpi") == 0)
  846.                     {
  847.                         /* Make sure these are valid parameters */
  848.                         int    newDpi, sizeInc, sizeMax, mySizeDiskFonts;
  849.  
  850.                         index++;
  851.                         if (index < commandMsg->cm_ArgC)
  852.                             newDpi = atoi(commandMsg->cm_ArgV[index]);
  853.                         else
  854.                             newDpi = 0;
  855.                         if (newDpi > 49)
  856.                         {
  857.                             /* check opencount */
  858.                             openCount = CountOpenFonts();
  859.                             if (openCount == 0)
  860.                             {
  861.                                 ClearUnusedATEFonts(fontList);
  862.                                 defaultDPI = newDpi;
  863.                                 /* reset ATEAvailFonts */
  864.                                 ObtainSemaphore(nafSemaphore);
  865.                                 mySizeDiskFonts = ateAvailFonts->aaf_SizeDiskFonts;
  866.                                 sizeInc = ateAvailFonts->aaf_SizeInc;
  867.                                 sizeMax = ateAvailFonts->aaf_SizeMax;
  868.                                 FreeVec(ateAvailFonts);
  869.                                 ateAvailFonts = 0;
  870.                                 ateAvailFonts = PrepATEAvailFonts(sizeMax, sizeInc, mySizeDiskFonts);
  871.                                 if (ateAvailFonts == 0)
  872.                                 {
  873.                                     fprintf(ateOutput, "Warning: System extremely low on memory\n");
  874.                                     fflush(ateOutput);
  875.                                     keepGoing = FALSE;
  876.                                 }
  877.                                 ReleaseSemaphore(nafSemaphore);
  878.                             }
  879.                             else
  880.                             {
  881.                                 fprintf(ateOutput,
  882.                                 "Cannot change default DPI unless you close all apps\n"
  883.                                 "using ATE fonts.\n");
  884.                                 fflush(ateOutput);
  885.                             }
  886.                         }
  887.                         else
  888.                         {
  889.                             fprintf(ateOutput, "DPI choice set too small, use DPI greater than 50.\n");
  890.                             fflush(ateOutput);
  891.                         }
  892.                     }
  893.                     if (strcmp(commandMsg->cm_ArgV[index], "-hidediskfonts") == 0)
  894.                     {
  895.                         ObtainSemaphore(nafSemaphore);
  896.                         /* First check to see if diskfonts are
  897.                            already hidden */
  898.                         if (ateAvailFonts->aaf_SizeDiskFonts != 0)
  899.                         {
  900.                             int    sizeMax, sizeInc;
  901.  
  902.                             sizeMax = ateAvailFonts->aaf_SizeMax;
  903.                             sizeInc = ateAvailFonts->aaf_SizeInc;
  904.                             FreeVec(ateAvailFonts);
  905.                             ateAvailFonts = 0;
  906.                             ateAvailFonts = PrepATEAvailFonts(sizeMax, sizeInc, 0);
  907.                             if (ateAvailFonts == 0)
  908.                             {
  909.                                 fprintf(ateOutput, "Warning: System extremely low on memory\n");
  910.                                 fflush(ateOutput);
  911.                                 keepGoing = FALSE;
  912.                             }
  913.                         }
  914.                         else
  915.                         {
  916.                             fprintf(ateOutput, "Amiga diskfonts already hidden.  No changes made.\n");
  917.                             fflush(ateOutput);
  918.                         }
  919.                         ReleaseSemaphore(nafSemaphore);
  920.                     }
  921.                     if (strcmp(commandMsg->cm_ArgV[index], "-showdiskfonts") == 0)
  922.                     {
  923.                         ObtainSemaphore(nafSemaphore);
  924.                         /* Check to see if we're already showing diskfonts */
  925.                         if (ateAvailFonts->aaf_SizeDiskFonts == 0)
  926.                         {
  927.                             int    mySizeDiskFonts, sizeMax, sizeInc;
  928.  
  929.                             sizeMax = ateAvailFonts->aaf_SizeMax;
  930.                             sizeInc = ateAvailFonts->aaf_SizeInc;
  931.  
  932.                             mySizeDiskFonts = OldAvailFonts(readLine, 0, AFF_DISK | AFF_TAGGED, diskfontBase);
  933.                             ateAvailFonts = 0;
  934.                             ateAvailFonts = PrepATEAvailFonts(sizeMax, sizeInc, mySizeDiskFonts);
  935.                             if (ateAvailFonts == 0)
  936.                             {
  937.                                 fprintf(ateOutput, "Warning: System extremely low on memory\n");
  938.                                 fflush(ateOutput);
  939.                                 keepGoing = FALSE;
  940.                             }
  941.                         }
  942.                         else
  943.                         {
  944.                             fprintf(ateOutput, "Amiga diskfonts already visible.  No changes made.\n");
  945.                             fflush(ateOutput);
  946.                         }
  947.                         ReleaseSemaphore(nafSemaphore);
  948.                     }
  949.                     if (strcmp(commandMsg->cm_ArgV[index], "-softstyleson") == 0)
  950.                         optSoftStyles = TRUE;
  951.                     if (strcmp(commandMsg->cm_ArgV[index], "-softstylesoff") == 0)
  952.                         optSoftStyles = FALSE;
  953.                 }
  954.                 ReplyMsg((struct Message *)commandMsg);
  955.             }
  956.         }
  957.  
  958.         if (keepGoing == FALSE)
  959.         {
  960.             /* check open count */
  961.             openCount = CountOpenFonts();
  962.             if (openCount != 0)
  963.             {
  964.                 fprintf(ateOutput,  "WARNING: Some apps have ATE fonts in use!\n"
  965.                     "Either close all apps using ATE fonts and try again,\n"
  966.                     "or simply reboot (ATE won't cause data loss).\n");
  967.                 fprintf(ateOutput, "ATE open font count: %d\n", openCount);
  968.                 fflush(ateOutput);
  969.                 keepGoing = TRUE;
  970.             }
  971.             else
  972.             {
  973.                 RemPort(ateCmdPort);
  974.                 /* Clear out all ports */
  975.                 while (diskfontMsg = (struct DiskfontMsg *)GetMsg(ateODFPort))
  976.                 {
  977.                     diskfontMsg->df_ATEFont = FALSE;
  978.                     ReplyMsg((struct Message *)diskfontMsg);
  979.                 }
  980.                 while (textMsg = (struct textMsg *)GetMsg(ateTextPort))
  981.                 {
  982.                     textMsg->tm_ATEFont = FALSE;
  983.                     ReplyMsg((struct Message *)textMsg);
  984.                 }
  985.                 while (sssMsg = (struct sssMsg *)GetMsg(ateSSSPort))
  986.                 {
  987.                     sssMsg->ss_ATEFont = FALSE;
  988.                     ReplyMsg((struct Message *)sssMsg);
  989.                 }
  990.                 while (commandMsg = (struct CommandMsg *)GetMsg(ateCmdPort))
  991.                 {
  992.                     ReplyMsg((struct Message *)commandMsg);
  993.                 }
  994.                 while (nsdfMsg = (struct NSDFMsg *)GetMsg(ateNSDFPort))
  995.                 {
  996.                     ReplyMsg((struct Message *)nsdfMsg);
  997.                 }
  998.                 keepGoing = FALSE;
  999.                 break;
  1000.             }
  1001.         }
  1002.         if ((signal & dfeSig))
  1003.         {
  1004.             ClearUnusedATEFonts(fontList);
  1005.             SetSignal(0, dfeSig);
  1006.         }
  1007.         if (signal & nsdfSig)
  1008.         {
  1009.             while (nsdfMsg = (struct NsdfMsg *)GetMsg(ateNSDFPort))
  1010.             {
  1011.                 nsdfMsg->nsdf_DFHeader = BuildScaledDiskFont(nsdfMsg->nsdf_TextFont, nsdfMsg->nsdf_TextAttr);
  1012.                 ReplyMsg((struct Message *)nsdfMsg);
  1013.             }
  1014.         }
  1015.         if ((signal & textSig))
  1016.         {
  1017.             while (textMsg = (struct TextMsg *)GetMsg(ateTextPort))
  1018.             {
  1019.                 keepGoing = AddATEChars(fontList, textMsg);
  1020.                 if (keepGoing == FALSE)
  1021.                 {
  1022.                     PSTrace("%%Out of memory or some other error drawing new chars\n");
  1023.                     psError = 0;
  1024.                 }
  1025.                 keepGoing = TRUE;
  1026.                 ReplyMsg((struct Message *)textMsg);
  1027.             }
  1028.         }
  1029.         if ((signal & odfSig))
  1030.         {
  1031.             while (diskfontMsg = (struct DiskfontMsg *)GetMsg(ateODFPort))
  1032.             {
  1033.                 keepGoing = AddATEFont(fontList, diskfontMsg);
  1034.                 if (keepGoing == FALSE)
  1035.                 {
  1036.                     PSTrace("%%Out of memory creating new textfont\n");
  1037.                     psError = 0;
  1038.                 }
  1039.                 keepGoing = TRUE;
  1040.                 ReplyMsg((struct Message *)diskfontMsg);
  1041.             }
  1042.         }
  1043.         if ((signal & sssSig))
  1044.         {
  1045.             while (sssMsg = (struct SSStyleMsg *)GetMsg(ateSSSPort))
  1046.             {
  1047.                 keepGoing = AddATEStyle(fontList, sssMsg);
  1048.                 if (keepGoing == FALSE)
  1049.                 {
  1050.                     PSTrace("%%Out of memory creating new textfont for new style\n");
  1051.                     psError = 0;
  1052.                 }
  1053.                 keepGoing = TRUE;
  1054.                 ReplyMsg((struct Message *)sssMsg);
  1055.             }
  1056.         }
  1057.     }
  1058.  
  1059.     /* Clean up time */
  1060.     Forbid();
  1061.     /* There is a proper way to undo these, but I'm too lazy */
  1062.     newNSDFPtr = SetFunction(diskfontBase, -0x36, oldNSDFPtr);
  1063.     newFuncPtr = SetFunction(diskfontBase, -0x1E, oldFuncPtr);
  1064.     newTextPtr = SetFunction(gfxBase, -0x3C, oldTextPtr);
  1065.     newSSSPtr = SetFunction(gfxBase, -0x5A, oldSSSPtr);
  1066.     newAFPtr = SetFunction(diskfontBase, -0x24, oldAFPtr);
  1067.     newDFEPtr = SetFunction(diskfontBase, -0x12, oldDFEPtr);
  1068. //    newTLPtr = SetFunction(gfxBase, -0x36, oldTLPtr);
  1069. //    newTEPtr = SetFunction(gfxBase, -0x2B2, oldTEPtr);
  1070.     Permit();
  1071.     fprintf(ateOutput, "Patches removed, cleaning up...");
  1072.     DeleteMsgPort(ateCmdPort);
  1073.     DeleteMsgPort(ateODFPort);
  1074.     DeleteMsgPort(ateTextPort);
  1075.     DeleteMsgPort(ateSSSPort);
  1076.     DeleteMsgPort(ateNSDFPort);
  1077.     FreeSignal(ateDfeSigBit);
  1078.     ClearFontNames(fontList);
  1079.     ObtainSemaphore(ateSemaphore);
  1080.     ReleaseSemaphore(ateSemaphore);
  1081.     FreeVec(ateFontList);
  1082.     ObtainSemaphore(nafSemaphore);
  1083.     ReleaseSemaphore(nafSemaphore);
  1084.     FreeVec(ateAvailFonts);
  1085.     fclose(nilInput);
  1086.     PSdeleteact(psActivation);
  1087.     FreeVec(psParm);
  1088.     CloseLibrary(PSbase);
  1089.     CloseLibrary(gfxBase);
  1090.     CloseLibrary(diskfontBase);
  1091.  
  1092.     fprintf(ateOutput, "Now exiting.\nRemember: This is BETA software!  Use at own risk!\n");
  1093.     return(0);
  1094. }
  1095.  
  1096. void ClearFontNames(struct List *fontList)
  1097. {
  1098. struct    FontNode    *workNode, *nextNode;
  1099. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  1100.  
  1101.     ObtainSemaphore(ateSemaphore);
  1102.     workNode = (struct FontNode *)(fontList->lh_Head);
  1103.     while (nextNode = (struct FontNode *)(workNode->fn_Node.ln_Succ))
  1104.     {
  1105.         if (workNode->fn_TextFont != 0)
  1106.         {
  1107.             RemFont(workNode->fn_TextFont);
  1108.             StripFont(workNode->fn_TextFont);
  1109.             FreeMem(workNode->fn_ExtDFHeader, workNode->fn_ExtDFHeader->edf_Length);
  1110. //            FreeVec(workNode->fn_TextFont);
  1111.         }
  1112.         FreeVec(workNode);
  1113.         workNode = nextNode;
  1114.     }
  1115.     ReleaseSemaphore(ateSemaphore);
  1116.     return;
  1117. }
  1118.  
  1119. BOOL AddATEChars(struct List *fontList, struct TextMsg *textMsg)
  1120. {
  1121. struct    FontNode    *fontNode;
  1122.     char        *builtChars;
  1123.     STRPTR        oneChar;
  1124.     UBYTE        indexY;
  1125.     BOOL        callMakeATEChars = FALSE;
  1126.     BOOL        addATECharsOK;
  1127.     WORD        indexX, length;
  1128.  
  1129.     /* Needed fontnode already found by the Text() patch. */
  1130.  
  1131.     fontNode = textMsg->tm_FontNode;
  1132.  
  1133.     if (fontNode != 0)
  1134.     {
  1135.         /* begin pre-scan, determine what chars really need to be drawn */
  1136.         length = textMsg->tm_Length;
  1137.         builtChars = fontNode->fn_BuiltChars;
  1138.         oneChar = (textMsg->tm_Chars);
  1139.         for (indexX = 0; indexX < length; indexX++)
  1140.         {
  1141.             /* Mark needed characters */
  1142.             indexY = oneChar[indexX];
  1143.             if (builtChars[indexY] == CHAR_NOT_DRAWN)
  1144.             {
  1145.                 builtChars[indexY] = CHAR_NEEDED;
  1146.                 callMakeATEChars = TRUE;
  1147.             }
  1148.         }
  1149.         textMsg->tm_ATEFont = TRUE;
  1150.         addATECharsOK = TRUE;
  1151.         if (callMakeATEChars == TRUE)
  1152.         {
  1153.             addATECharsOK = MakeATEChars(fontNode);
  1154.         }
  1155.     }
  1156.     else
  1157.     {
  1158.         textMsg->tm_ATEFont = FALSE;
  1159.         addATECharsOK = TRUE;
  1160.     }
  1161.  
  1162.     return(addATECharsOK);
  1163. }
  1164.  
  1165. BOOL AddATEFont(struct List *fontList, struct DiskfontMsg *diskfontMsg)
  1166. {
  1167. struct    TextAttr    *textAttr;
  1168. struct    TTextAttr    *taggedTextAttr;
  1169. struct    FontNode    *fontNode;
  1170. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  1171.     UBYTE        fontStyle;
  1172.     char        fontName[64], regularName[64], typefaceName[64];
  1173.     char        dummyString[80], *dotPtr, optFontEncoding;
  1174.     BOOL        addATEFontOK;
  1175.     FILE        *ateFile;
  1176.     int        lowChar, highChar;
  1177.     float        xDPI, yDPI;
  1178.     float        dpiRatio;
  1179. struct    TagItem        *dpiTag;
  1180.     ULONG        dpiData;
  1181.  
  1182.     textAttr = diskfontMsg->df_TextAttr;
  1183.     if (textAttr->ta_Style & FSF_TAGGED)
  1184.         taggedTextAttr = (struct TTextAttr *)textAttr;
  1185.     else
  1186.         taggedTextAttr = 0;
  1187.  
  1188.     /* Make sure the font in question is an ATE font. */
  1189.     strcpy(fontName, "FONTS:");
  1190.     strcat(fontName, textAttr->ta_Name);
  1191.     dotPtr = strchr(fontName, '.');
  1192.     *dotPtr = '\0';
  1193.     /* OK try opening the file */
  1194.     ateFile = fopen(fontName, "r");
  1195.     if (ateFile == 0)
  1196.     {
  1197.         diskfontMsg->df_ATEFont = FALSE;
  1198.         return(TRUE);
  1199.         /* hey, not an ATE-ready typeface so exit */
  1200.     }
  1201.     /* Now search to see if requested font already exists */
  1202.     textAttr = diskfontMsg->df_TextAttr;
  1203.     fontStyle = textAttr->ta_Style & (FSF_BOLD | FSF_ITALIC);
  1204.     sprintf(fontName, "%50s / %5d / %2x", textAttr->ta_Name, textAttr->ta_YSize, fontStyle);
  1205.     ObtainSemaphoreShared(ateSemaphore);
  1206.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  1207.     ReleaseSemaphore(ateSemaphore);
  1208.     if (fontNode != 0)
  1209.     {
  1210.         diskfontMsg->df_ATEFont = TRUE;
  1211.         diskfontMsg->df_TextFont = fontNode->fn_TextFont;
  1212.         return(TRUE);
  1213.         /* Hey, why work if you already have results? */
  1214.     }
  1215.  
  1216.     /* NOTE: ATE can only worry about substituting bold or italic versions, */
  1217.     /*       setting soft styles will take care of underlining */
  1218.  
  1219.     fgets(dummyString, 79, ateFile);
  1220.     sscanf(dummyString, "%c %d %d", &optFontEncoding, &lowChar, &highChar);
  1221.     dotPtr = strchr(dummyString, '.');
  1222.     dotPtr++;
  1223.     strcpy(regularName, dotPtr);
  1224.     strcpy(typefaceName, regularName);
  1225.     switch(fontStyle)
  1226.     {
  1227.         case 0x02:
  1228.             fgets(dummyString, 79, ateFile);
  1229.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1230.             dotPtr = strchr(dummyString, '.');
  1231.             dotPtr++;
  1232.             strcpy(typefaceName, dotPtr);
  1233.             break;
  1234.         case 0x04:
  1235.             fgets(dummyString, 79, ateFile);
  1236.             fgets(dummyString, 79, ateFile);
  1237.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1238.             dotPtr = strchr(dummyString, '.');
  1239.             dotPtr++;
  1240.             strcpy(typefaceName, dotPtr);
  1241.             break;
  1242.         case 0x06:
  1243.             fgets(dummyString, 79, ateFile);
  1244.             fgets(dummyString, 79, ateFile);
  1245.             fgets(dummyString, 79, ateFile);
  1246.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1247.             dotPtr = strchr(dummyString, '.');
  1248.             dotPtr++;
  1249.             strcpy(typefaceName, dotPtr);
  1250.             break;
  1251.         default:
  1252.             break;
  1253.     }
  1254.  
  1255.     fclose(ateFile);
  1256.     /* If no real typeface exists for desired style, use plain style */
  1257.     if (strcmp(typefaceName, regularName) == 0)
  1258.         fontStyle = FS_NORMAL;
  1259.  
  1260.     /* Build search string and see if we don't already have this font */
  1261.     sprintf(fontName, "%50s / %5d / %2x", textAttr->ta_Name, textAttr->ta_YSize, fontStyle);
  1262.     ObtainSemaphoreShared(ateSemaphore);
  1263.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  1264.     ReleaseSemaphore(ateSemaphore);
  1265.     if (fontNode != 0)
  1266.     {
  1267.         diskfontMsg->df_ATEFont = TRUE;
  1268.         diskfontMsg->df_TextFont = fontNode->fn_TextFont;
  1269.         return(TRUE);
  1270.         /* Hey, why work if you already have results? */
  1271.     }
  1272.  
  1273.     /* Original OpenDiskFont takes over here.  If the TA_DeviceDPI
  1274.        don't match, tough luck as per C= spec. */
  1275.  
  1276.     dpiData = 0;
  1277.     /* So no font node eh?  Time to make one. */
  1278.     if (taggedTextAttr != 0)
  1279.     {
  1280.         dpiTag = taggedTextAttr->tta_Tags;
  1281.         dpiData = GetTagData(TA_DeviceDPI, 0L, dpiTag);
  1282.  
  1283.         if (dpiData != 0)
  1284.         {
  1285.             xDPI = (dpiData & 0xFFFF0000) >> 16;
  1286.             yDPI = dpiData & 0x0000FFFF;
  1287.             dpiRatio = xDPI / yDPI;
  1288.             PSTrace("Typeface DPI: %d x, %d y\n", xDPI, yDPI);
  1289.             PSTrace("DPI ratio: %f\n", dpiRatio);
  1290.         }
  1291.  
  1292.     }
  1293.  
  1294.     /* Consider a function to allocate the entire node and TextFont too */
  1295.     fontNode = (struct FontNode *)AllocVec(sizeof(struct FontNode), MEMF_PUBLIC | MEMF_CLEAR);
  1296.     if (fontNode != 0)
  1297.     {
  1298.         strcpy(fontNode->fn_Name, fontName);
  1299.         fontNode->fn_Node.ln_Name = fontNode->fn_Name;
  1300.         fontNode->fn_Node.ln_Type = NT_USER;
  1301.         fontNode->fn_Node.ln_Pri = 0;
  1302.         strcpy(fontNode->fn_TypefaceName, typefaceName);
  1303.         dotPtr = strchr(fontNode->fn_TypefaceName, '\n');
  1304.         if (dotPtr != 0)
  1305.             *dotPtr = 0;
  1306.         fontNode->fn_LowChar = lowChar;
  1307.         fontNode->fn_HighChar = highChar;
  1308.         fontNode->fn_OptFontEncoding = optFontEncoding;
  1309.         fontNode->fn_Style = fontStyle;
  1310.         fontNode->fn_FontSize = textAttr->ta_YSize;
  1311.         if (dpiData != 0)
  1312.             fontNode->fn_XDPI = dpiRatio * defaultDPI;
  1313.         else
  1314.             fontNode->fn_XDPI = defaultDPI;
  1315.         PSTrace("X DPI for this font is %f\n", fontNode->fn_XDPI);
  1316.  
  1317.         fontNode->fn_TextFont = MakeATEFont(fontNode, textAttr);
  1318.         if (fontNode->fn_TextFont != 0)
  1319.         {
  1320.             AddFont(fontNode->fn_TextFont);
  1321.             diskfontMsg->df_TextFont = fontNode->fn_TextFont;
  1322.             diskfontMsg->df_ATEFont = TRUE;
  1323.             ObtainSemaphore(ateSemaphore);
  1324.             AddHead(fontList, (struct Node *)fontNode);
  1325.             ReleaseSemaphore(ateSemaphore);
  1326.             addATEFontOK = TRUE;
  1327.             if (dpiData != 0)
  1328.                 ExtendFont(fontNode->fn_TextFont, dpiTag);
  1329.             else
  1330.                 ExtendFont(fontNode->fn_TextFont, 0);
  1331.             fontNode->fn_BlackList = FALSE;
  1332.             /* Stupid kludge inserted to draw the Space character first, to work
  1333.                around a weird bug I have drawing the first char in a set. */
  1334.             fontNode->fn_BuiltChars[32] = CHAR_NEEDED;
  1335. //            MakeATEChars(fontNode);
  1336.             /* end of stupid kludge */
  1337.         }
  1338.         else
  1339.         {
  1340.             diskfontMsg->df_ATEFont = FALSE;
  1341.             addATEFontOK = FALSE;
  1342.             fontNode->fn_BlackList = TRUE;
  1343.             ObtainSemaphore(ateSemaphore);
  1344.             AddHead(fontList, (struct Node *)fontNode);
  1345.             ReleaseSemaphore(ateSemaphore);
  1346.         }
  1347.     }
  1348.     else
  1349.     {
  1350.         diskfontMsg->df_ATEFont = FALSE;
  1351.         addATEFontOK = FALSE;
  1352.     }
  1353.     return(addATEFontOK);
  1354. }
  1355.  
  1356. /* This function mimics AddATEFont except it adds fonts upon SetSoftStyle()
  1357.    calls instead of OpenDiskFont() calls.  This fcn takes special
  1358.    consideration of ta_Style flags. */
  1359. BOOL AddATEStyle(struct List *fontList, struct SSStyleMsg *sssMsg)
  1360. {
  1361. struct    FontNode    *fontNode;
  1362. struct    RastPort    *sssRastPort = sssMsg->ss_RastPort;
  1363. struct    TextFont    *sssTextFont = sssMsg->ss_RastPort->Font;
  1364. static struct    TextAttr    dummyAttr;    /* For calling MakeATEFont */
  1365. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  1366.     char        *currentFontName, fontName[64], dummyString[80], *dotPtr;
  1367.     char        typefaceName[64], regularName[64], optFontEncoding;
  1368.     int        fontSize, currentStyle, desiredStyle, lowChar, highChar;
  1369.     FILE        *ateFile;
  1370.     int        xDPI;    /* Check if the normal font has a ratio */
  1371.     BOOL        addATEStyleOK;
  1372.  
  1373.     currentFontName = sssRastPort->Font->tf_Message.mn_Node.ln_Name;
  1374.     fontSize = sssRastPort->Font->tf_YSize;
  1375.     desiredStyle = sssMsg->ss_NewStyle & sssMsg->ss_Enable;
  1376.     currentStyle = desiredStyle & (FSF_BOLD | FSF_ITALIC);
  1377.     /* Only pay attention to FSF_BOLD and FSF_ITALIC */
  1378.     /* Build search string and see if we don't already have this font */
  1379.     sprintf(fontName, "%50s / %5d / %2x", currentFontName, fontSize, currentStyle);
  1380.     ObtainSemaphoreShared(ateSemaphore);
  1381.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  1382.     ReleaseSemaphore(ateSemaphore);
  1383.     if (fontNode != 0)
  1384.     {
  1385.         sssMsg->ss_ATEFont = TRUE;
  1386.         sssMsg->ss_ChangedFont = fontNode->fn_TextFont;
  1387.         sssMsg->ss_SoftStyleNeeded = currentStyle ^ desiredStyle;
  1388.         return(TRUE);
  1389.         /* Hey, why work if you already have results? */
  1390.     }
  1391.  
  1392.     /* Do repeat search for normal style and copy XDPI */
  1393.     sprintf(fontName, "%50s / %5d / %2x", currentFontName, fontSize, FS_NORMAL);
  1394.     ObtainSemaphoreShared(ateSemaphore);
  1395.     fontNode = (struct FontNode *)FindName(fontList, fontName);
  1396.     ReleaseSemaphore(ateSemaphore);
  1397.     if (fontNode != 0)
  1398.         xDPI = fontNode->fn_XDPI;
  1399.  
  1400.     /* OK currentStyle doesn't exist yet and it IS an ATE font.  So make it. */
  1401.     
  1402.     /* Make sure the font in question is an ATE font. */
  1403.     strcpy(fontName, "FONTS:");
  1404.     strcat(fontName, currentFontName);
  1405.     dotPtr = strchr(fontName, '.');
  1406.     *dotPtr = '\0';
  1407.     /* OK try opening the file */
  1408.     ateFile = fopen(fontName, "r");
  1409.     if (ateFile == 0)
  1410.     {
  1411.         sssMsg->ss_ATEFont = FALSE;
  1412.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  1413.         return(TRUE);
  1414.         /* hey, not an ATE-ready typeface so exit */
  1415.     }
  1416.  
  1417.     /* Now search to see if requested typeface version exists */
  1418.     fgets(dummyString, 79, ateFile);
  1419.     sscanf(dummyString, "%c %d %d", &optFontEncoding, &lowChar, &highChar);
  1420.     dotPtr = strchr(dummyString, '.');
  1421.     dotPtr++;
  1422.     strcpy(regularName, dotPtr);
  1423.     strcpy(typefaceName, regularName);
  1424.     switch(currentStyle)
  1425.     {
  1426.         case 0x02:    /* FSF_BOLD */
  1427.             fgets(dummyString, 79, ateFile);
  1428.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1429.             dotPtr = strchr(dummyString, '.');
  1430.             dotPtr++;
  1431.             strcpy(typefaceName, dotPtr);
  1432.             break;
  1433.         case 0x04:    /* FSF_ITALIC */
  1434.             fgets(dummyString, 79, ateFile);
  1435.             fgets(dummyString, 79, ateFile);
  1436.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1437.             dotPtr = strchr(dummyString, '.');
  1438.             dotPtr++;
  1439.             strcpy(typefaceName, dotPtr);
  1440.             break;
  1441.         case 0x06:    /* FSF_BOLD | FSF_ITALIC */
  1442.             fgets(dummyString, 79, ateFile);
  1443.             fgets(dummyString, 79, ateFile);
  1444.             fgets(dummyString, 79, ateFile);
  1445.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1446.             dotPtr = strchr(dummyString, '.');
  1447.             dotPtr++;
  1448.             strcpy(typefaceName, dotPtr);
  1449.             break;
  1450.         default:
  1451.             break;
  1452.     }
  1453.     fclose(ateFile);
  1454.  
  1455.     /* If no real typeface exists for desired style, exit */
  1456.     if (strcmp(typefaceName, regularName) == 0)
  1457.     {
  1458.         sssMsg->ss_ATEFont = FALSE;
  1459.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  1460.         return(TRUE);
  1461.     }
  1462.  
  1463.     /* OK now make a new font node for this new style */
  1464.     fontNode = (struct FontNode *)AllocVec(sizeof(struct FontNode), MEMF_PUBLIC | MEMF_CLEAR);
  1465.     if (fontNode != 0)
  1466.     {
  1467.         sprintf(fontName, "%50s / %5d / %2x", currentFontName, fontSize, currentStyle);
  1468.         strcpy(fontNode->fn_Name, fontName);
  1469.         fontNode->fn_Node.ln_Name = fontNode->fn_Name;
  1470.         fontNode->fn_Node.ln_Type = NT_USER;
  1471.         fontNode->fn_Node.ln_Pri = 0;
  1472.         strcpy(fontNode->fn_TypefaceName, typefaceName);
  1473.         dotPtr = strchr(fontNode->fn_TypefaceName, '\n');
  1474.         if (dotPtr != 0)
  1475.             *dotPtr = 0;
  1476.         fontNode->fn_LowChar = lowChar;
  1477.         fontNode->fn_HighChar = highChar;
  1478.         fontNode->fn_OptFontEncoding = optFontEncoding;
  1479.         fontNode->fn_Style = currentStyle;
  1480.         fontNode->fn_FontSize = fontSize;
  1481.         fontNode->fn_XDPI = xDPI;
  1482.         dummyAttr.ta_Name = currentFontName;
  1483.         dummyAttr.ta_YSize = fontSize;
  1484.         dummyAttr.ta_Style = currentStyle;
  1485.         dummyAttr.ta_Flags = 0;
  1486.         /* Call MakeATEFont() to build this new font */
  1487.         fontNode->fn_TextFont = MakeATEFont(fontNode, &dummyAttr);
  1488.         if (fontNode->fn_TextFont != 0)
  1489.         {
  1490.             AddFont(fontNode->fn_TextFont);
  1491.             sssMsg->ss_ChangedFont = fontNode->fn_TextFont;
  1492.             sssMsg->ss_ATEFont = TRUE;
  1493.             ObtainSemaphore(ateSemaphore);
  1494.             AddHead(fontList, (struct Node *)fontNode);
  1495.             ReleaseSemaphore(ateSemaphore);
  1496.             ExtendFont(fontNode->fn_TextFont, 0);
  1497.             sssMsg->ss_SoftStyleNeeded = currentStyle ^ desiredStyle;
  1498.             addATEStyleOK = TRUE;
  1499.             fontNode->fn_BlackList = FALSE;
  1500.             /* Stupid kludge inserted to draw the Space character first, to work
  1501.                around a weird bug I have drawing the first char in a set. */
  1502.             fontNode->fn_BuiltChars[32] = CHAR_NEEDED;
  1503. //            MakeATEChars(fontNode);
  1504.             /* end of stupid kludge */
  1505.         }
  1506.         else
  1507.         {
  1508.             sssMsg->ss_ATEFont = FALSE;
  1509.             addATEStyleOK = FALSE;
  1510.             sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  1511.             fontNode->fn_BlackList = TRUE;
  1512.         }
  1513.     }
  1514.     else
  1515.     {
  1516.         sssMsg->ss_ATEFont = FALSE;
  1517.         sssMsg->ss_SoftStyleNeeded = sssMsg->ss_NewStyle;
  1518.         addATEStyleOK = FALSE;
  1519.     }
  1520.     return(addATEStyleOK);
  1521. }
  1522.  
  1523. /* Yet another mimic-er of AddATEFont, except this one builds SegLists and
  1524.    clears the fontnode after use.  Used for the NewScaledDiskFont() patch */
  1525. struct DiskFontHeader *BuildScaledDiskFont(struct TextFont *textFont, struct TextAttr *textAttr)
  1526. {
  1527. struct    TTextAttr    *taggedTextAttr;
  1528. struct    FontNode    *fontNode;
  1529. struct    DiskFontHeader    *dfHeader;
  1530.     UBYTE        fontStyle;
  1531.     char        fontName[64], regularName[64], typefaceName[64];
  1532.     char        dummyString[80], *dotPtr, optFontEncoding;
  1533.     FILE        *ateFile;
  1534.     int        lowChar, highChar, index;
  1535.     BOOL        addATEFontOK = FALSE;
  1536.     float        xDPI, yDPI;
  1537.     float        dpiRatio;
  1538. struct    TagItem        *dpiTag;
  1539.     ULONG        dpiData;
  1540.  
  1541.     if (textAttr->ta_Style & FSF_TAGGED)
  1542.         taggedTextAttr = (struct TTextAttr *)textAttr;
  1543.     else
  1544.         taggedTextAttr = 0;
  1545.  
  1546.     /* Make sure the font in question is an ATE font. */
  1547.     strcpy(fontName, "FONTS:");
  1548.     strcat(fontName, textFont->tf_Message.mn_Node.ln_Name);
  1549.     dotPtr = strchr(fontName, '.');
  1550.     *dotPtr = '\0';
  1551.     /* OK try opening the file */
  1552.     ateFile = fopen(fontName, "r");
  1553.     if (ateFile == 0)
  1554.         return(0);
  1555.  
  1556.     fontStyle = (textAttr->ta_Style) & (FSF_BOLD | FSF_ITALIC);
  1557.  
  1558.     fgets(dummyString, 79, ateFile);
  1559.     sscanf(dummyString, "%c %d %d", &optFontEncoding, &lowChar, &highChar);
  1560.     dotPtr = strchr(dummyString, '.');
  1561.     dotPtr++;
  1562.     strcpy(regularName, dotPtr);
  1563.     strcpy(typefaceName, regularName);
  1564.     switch(fontStyle)
  1565.     {
  1566.         case 0x02:
  1567.             fgets(dummyString, 79, ateFile);
  1568.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1569.             dotPtr = strchr(dummyString, '.');
  1570.             dotPtr++;
  1571.             strcpy(typefaceName, dotPtr);
  1572.             break;
  1573.         case 0x04:
  1574.             fgets(dummyString, 79, ateFile);
  1575.             fgets(dummyString, 79, ateFile);
  1576.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1577.             dotPtr = strchr(dummyString, '.');
  1578.             dotPtr++;
  1579.             strcpy(typefaceName, dotPtr);
  1580.             break;
  1581.         case 0x06:
  1582.             fgets(dummyString, 79, ateFile);
  1583.             fgets(dummyString, 79, ateFile);
  1584.             fgets(dummyString, 79, ateFile);
  1585.             sscanf(dummyString, "&c %d %d", &optFontEncoding, &lowChar, &highChar);
  1586.             dotPtr = strchr(dummyString, '.');
  1587.             dotPtr++;
  1588.             strcpy(typefaceName, dotPtr);
  1589.             break;
  1590.         default:
  1591.             break;
  1592.     }
  1593.  
  1594.     fclose(ateFile);
  1595.     /* If no real typeface exists for desired style, use plain style */
  1596.     if (strcmp(typefaceName, regularName) == 0)
  1597.         fontStyle = FS_NORMAL;
  1598.  
  1599.     dpiData = 0;
  1600.     if (taggedTextAttr != 0)
  1601.     {
  1602.         dpiTag = taggedTextAttr->tta_Tags;
  1603.         dpiData = GetTagData(TA_DeviceDPI, 0L, dpiTag);
  1604.  
  1605.         if (dpiData != 0)
  1606.         {
  1607.             xDPI = (dpiData & 0xFFFF0000) >> 16;
  1608.             yDPI = dpiData & 0x0000FFFF;
  1609.             dpiRatio = xDPI / yDPI;
  1610.             PSTrace("Typeface DPI: %d x, %d y\n", xDPI, yDPI);
  1611.             PSTrace("DPI ratio: %f\n", dpiRatio);
  1612.         }
  1613.  
  1614.     }
  1615.  
  1616.     fontNode = (struct FontNode *)AllocVec(sizeof(struct FontNode), MEMF_PUBLIC | MEMF_CLEAR);
  1617.     if (fontNode != 0)
  1618.     {
  1619.         strcpy(fontNode->fn_Name, fontName);
  1620.         fontNode->fn_Node.ln_Name = fontNode->fn_Name;
  1621.         fontNode->fn_Node.ln_Type = NT_USER;
  1622.         fontNode->fn_Node.ln_Pri = 0;
  1623.         strcpy(fontNode->fn_TypefaceName, typefaceName);
  1624.         dotPtr = strchr(fontNode->fn_TypefaceName, '\n');
  1625.         if (dotPtr != 0)
  1626.             *dotPtr = 0;
  1627.         fontNode->fn_LowChar = lowChar;
  1628.         fontNode->fn_HighChar = highChar;
  1629.         fontNode->fn_OptFontEncoding = optFontEncoding;
  1630.         fontNode->fn_Style = fontStyle;
  1631.         fontNode->fn_FontSize = textAttr->ta_YSize;
  1632.         if (dpiData != 0)
  1633.             fontNode->fn_XDPI = dpiRatio * defaultDPI;
  1634.         else
  1635.             fontNode->fn_XDPI = defaultDPI;
  1636.         PSTrace("X DPI for this font is %f\n", fontNode->fn_XDPI);
  1637.  
  1638.         fontNode->fn_TextFont = MakeATEFont(fontNode, textAttr);
  1639.         if (fontNode->fn_TextFont != 0)
  1640.         {
  1641.             if (dpiData != 0)
  1642.                 ExtendFont(fontNode->fn_TextFont, dpiTag);
  1643. //            else
  1644. //                ExtendFont(fontNode->fn_TextFont, 0);
  1645.             /* Build all characters */
  1646.             for (index = lowChar; index <= highChar; index++)
  1647.                 fontNode->fn_BuiltChars[index] = CHAR_NEEDED;
  1648.             addATEFontOK = MakeATEChars(fontNode);
  1649.         }
  1650.         else
  1651.         {
  1652.             addATEFontOK = FALSE;
  1653.             fontNode->fn_BlackList = TRUE;
  1654.         }
  1655.     }
  1656.     else
  1657.     {
  1658.         addATEFontOK = FALSE;
  1659.         return(0);
  1660.     }
  1661.  
  1662.     if (addATEFontOK == FALSE)
  1663.     {
  1664.         PSTrace("%%Error building scaled diskfont\n");
  1665.         FreeMem(fontNode->fn_ExtDFHeader, fontNode->fn_ExtDFHeader->edf_Length);
  1666.         FreeVec(fontNode);
  1667.         return(0);
  1668.     }
  1669.     dfHeader = &fontNode->fn_ExtDFHeader->edf_DFHeader;
  1670.     FreeVec(fontNode);
  1671.     return(dfHeader);
  1672.  
  1673. }
  1674.  
  1675. /* Here we build a new TextFont */
  1676. struct TextFont *MakeATEFont(struct FontNode *fontNode, struct TextAttr *textAttr)
  1677. {
  1678. struct    TextFont    *newFont;
  1679. struct    ExtDFHeader    *extDFHeader;
  1680.     FILE        *afmFile;
  1681.     char        lineIn[256], afmFilename[64], checkString[64], charName[24];
  1682.     int        zZ, z1, z2, index, y1, y2;
  1683.     int        asciiCode, llX, llY, urX, urY, xWidth;
  1684. //structPSdevice    *localPage = &fontNode->fn_Page;
  1685.  
  1686.     if (fontNode->fn_BlackList == TRUE)
  1687.         return(0);
  1688.     /* Pre-check: Make sure the typeface is in PSFonts: */
  1689.     strcpy(afmFilename, "PSFonts:");
  1690.     strcat(afmFilename, fontNode->fn_TypefaceName);
  1691.     afmFile = fopen(afmFilename, "r");
  1692.     if (afmFile == 0)
  1693.     {
  1694.         fprintf(ateOutput, "Cannot locate typeface file %s.  Check your _AFM_ files or\n"
  1695.                "Re-install the typeface.\n", fontNode->fn_TypefaceName);
  1696.         fflush(ateOutput);
  1697.         fclose(afmFile);
  1698.         return(0);
  1699.     }
  1700.  
  1701.     /* Find AFM and encoding files and get charWidth & bounding box info */
  1702.     strcpy(afmFilename, "PSFonts:afms/");
  1703.     strcat(afmFilename, fontNode->fn_TypefaceName);
  1704.     strcat(afmFilename, ".afm");
  1705.     PSTrace("%%Will attempt to open %s\n", afmFilename);
  1706.     afmFile = fopen(afmFilename, "r");
  1707.     if (afmFile == 0)
  1708.     {
  1709.         PSTrace("%%Can't open AFM file\n");
  1710.         fprintf(ateOutput, "Cannot locate AFM file for typeface %s.  Check your\n"
  1711.                "PSFonts/afms diectory and _ATE_ files or re-install.\n",
  1712.                fontNode->fn_TypefaceName);
  1713.         fflush(ateOutput);
  1714.         fclose(afmFile);
  1715.         return(0);
  1716.     }
  1717.  
  1718.     /* NOTICE: This routine looks for specific keywords and I'm not responsible
  1719.        if you don't use AFMs that follow Adobe FontMetrics2.0.  Also notice:
  1720.        I do not check the typeface names in the .afm itself.  The Install prg
  1721.        will do that stupid checking when I finish it. */
  1722.  
  1723.     fontNode->fn_OptBaseLine = 0;
  1724.     /* Search for FontBBox keyword */
  1725.     while (!feof(afmFile))
  1726.     {
  1727.         fgets(lineIn, 256, afmFile);
  1728.         sscanf(lineIn, "%s ", checkString);
  1729.         if (strcmp(checkString, "FontBBox") == 0)
  1730.         {
  1731.             llY = 0;
  1732.             sscanf(lineIn, "%s %d %d %d %d", checkString, &llX, &llY, &urX, &urY);
  1733.             PSTrace("%%Bounding box: %d %d %d %d\n", llX, llY, urX, urY);
  1734.             if (llY < 0)
  1735.                 fontNode->fn_OptBaseLine = -llY;
  1736.             if (llY > 0)
  1737.                 fontNode->fn_OptBaseLine = llY;
  1738.             PSTrace("%%Baseline read from AFM file at %d\n", fontNode->fn_OptBaseLine);
  1739.             break;
  1740.         }
  1741.     }
  1742.  
  1743.     /* Search for StartCharMetrics keyword */
  1744.     while (!feof(afmFile))
  1745.     {
  1746.         fgets(lineIn, 256, afmFile);
  1747.         sscanf(lineIn, "%s ", checkString);
  1748.         if (strcmp(checkString, "StartCharMetrics") == 0)
  1749.             break;
  1750.     }
  1751.     if (feof(afmFile))
  1752.     {
  1753.         fprintf(ateOutput, "Error parsing AFM file for %s.  Ensure the AFM follows\n"
  1754.                "AdobeFontMetrics 2.0 spec, including bounding boxes for\n"
  1755.                "each character.\n", fontNode->fn_TypefaceName);
  1756.         fflush(ateOutput);
  1757.         fclose(afmFile);
  1758.         return(0);
  1759.     }
  1760.  
  1761.     /* OK very next statements until EndCharMetrics are width and bounding box
  1762.        info.  Read it all in, compare charnames with encodingExternal and build
  1763.        width and bbox info.  */
  1764.  
  1765.     while (!feof(afmFile))
  1766.     {
  1767.         asciiCode = 0;
  1768.         fgets(lineIn, 256, afmFile);
  1769.         sscanf(lineIn, "%s", checkString);
  1770.         if (strcmp(checkString, "EndCharMetrics") == 0)
  1771.             break;
  1772.         sscanf(lineIn, "C %d ; WX %d ; N %s ; B %d %d %d %d",
  1773.             &asciiCode, &xWidth, charName, &llX, &llY, &urX, &urY);
  1774.  
  1775.         if (asciiCode == -1)
  1776.         {
  1777.             for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index++)
  1778.             {
  1779.                 if (strcmp(encodingExternal[index], charName) == 0)
  1780.                 {
  1781.                     if (urX - llX < xWidth)
  1782.                         urX = xWidth;
  1783.                     fontNode->fn_CharWidths[index] = xWidth;
  1784.                     fontNode->fn_LowLeftX[index] = llX;
  1785.                     fontNode->fn_LowLeftY[index] = llY;
  1786.                     fontNode->fn_UpRightX[index] = urX;
  1787.                     fontNode->fn_UpRightY[index] = urY;
  1788.                     break;
  1789.                 }
  1790.             }
  1791.         }
  1792.         else
  1793.         {
  1794.             if ((urX - llX) < xWidth)
  1795.                 urX = xWidth;
  1796.             fontNode->fn_CharWidths[asciiCode] = xWidth;
  1797.             fontNode->fn_LowLeftX[asciiCode] = llX;
  1798.             fontNode->fn_LowLeftY[asciiCode] = llY;
  1799.             fontNode->fn_UpRightX[asciiCode] = urX;
  1800.             fontNode->fn_UpRightY[asciiCode] = urY;
  1801.         }
  1802.     }
  1803.  
  1804.     if (feof(afmFile))
  1805.     {
  1806.         PSTrace("%%Disk error or format error reading AFM file\n");
  1807.         fclose(afmFile);
  1808.         return(0);
  1809.     }
  1810.  
  1811.     /* Since AddATEFont() did all the checking for this fcn, just start rendering */
  1812.     PSTrace("%%Loading typeface %s\n", fontNode->fn_TypefaceName);
  1813.     /* A bit of weeding out; these weren't needed */
  1814. //    PSIntf("/fontname /%.100s def\n", fontNode->fn_TypefaceName);
  1815. //    PSIntf("fontname findfont pop\n");
  1816. //    PSIntf("/font fontname .findfont def\n");
  1817.  
  1818.     PSIntf("/font /%.100s findfont def\n", fontNode->fn_TypefaceName);
  1819.  
  1820.     if (psError != 0)
  1821.         PSTrace("%%Error loading typeface\n");
  1822.     PSTrace("%%Encoding font\n");
  1823.     PSIntf("/newfont font maxlength dict def\n");
  1824.     PSIntf(    "font\n"
  1825.         "{ exch dup /FID ne"
  1826.         "{ exch newfont 3 1 roll put } { pop pop } ifelse }\n"
  1827.         "forall\n");
  1828.     if (fontNode->fn_OptFontEncoding == 'S')
  1829.         PSIntf("newfont /Encoding encoding put\n");
  1830.     PSIntf("/_%.100s newfont definefont pop\n", fontNode->fn_TypefaceName);
  1831.     if (psError != 0)
  1832.     {
  1833.         PSTrace("%%PostScript error encoding typeface\n");
  1834.         return(0);
  1835.     }
  1836.  
  1837.     if (fontNode->fn_OptBaseLine == 0)
  1838.     {
  1839.         /* Start generating baseline info from BBox info */
  1840.         zZ = 1000 * 72 / defaultDPI;    /* Formerly zZ = (1000 * 72) / optYDen */
  1841.         z1 = z2 = 0;
  1842.         for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index++)
  1843.         {
  1844.             if (fontNode->fn_LowLeftY[index] < z1)
  1845.                 z1 = fontNode->fn_LowLeftY[index];
  1846.             if (fontNode->fn_UpRightY[index] > z2)
  1847.                 z2 = fontNode->fn_UpRightY[index];
  1848.         }
  1849.         if (z2 == z1)
  1850.         {
  1851.             PSTrace("%%All chars in this typeface are null!\n");
  1852.             psError = -1;
  1853.             return(0);
  1854.         }
  1855.         fontNode->fn_OptBaseLine = (1000 * (-z1) + (z2 - z1) / 2) / (z2 - z1);
  1856.         if ((z2 - z1 > zZ) && fontNode->fn_OptFontEncoding == 'S')
  1857.         {
  1858.             y1 = y2 = 0;
  1859.             for (index = 'A'; index <= 'Z'; index++)
  1860.             {
  1861.                 if (fontNode->fn_LowLeftY[index] < y1)
  1862.                     y1 = fontNode->fn_LowLeftY[index];
  1863.                 if (fontNode->fn_UpRightY[index] > y2)
  1864.                     y2 = fontNode->fn_UpRightY[index];
  1865.             }
  1866.             for (index = 'a'; index <= 'z'; index++)
  1867.             {
  1868.                 if (fontNode->fn_LowLeftY[index] < y1)
  1869.                     y1 = fontNode->fn_LowLeftY[index];
  1870.                 if (fontNode->fn_UpRightY[index] > y2)
  1871.                     y2 = fontNode->fn_UpRightY[index];
  1872.             }
  1873.             if (y2 - y1 <= zZ)
  1874.                 fontNode->fn_OptBaseLine = (1000 * (-y1) + zZ / 2) / zZ;
  1875.             else
  1876.                 fontNode->fn_OptBaseLine = (1000 * (-y1) + (y2 - y1) / 2) / (y2 - y1);
  1877.         }
  1878.     }
  1879.  
  1880.     PSTrace("%%Baseline set to %d/1000 of pixel height\n", fontNode->fn_OptBaseLine);
  1881.  
  1882.     /* Prepare memory space for the new font */
  1883.     PSTrace("%%Allocating space for new TextFont\n");
  1884.     fontNode->fn_BaseLength = sizeof(struct ExtDFHeader) + 8 * (fontNode->fn_HighChar - fontNode->fn_LowChar + 2);
  1885.     fontNode->fn_MaxWidth = 0;
  1886.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index++)
  1887.         fontNode->fn_MaxWidth += (((fontNode->fn_UpRightX[index] * 1.3) -
  1888.         fontNode->fn_LowLeftX[index]) * fontNode->fn_FontSize * fontNode->fn_XDPI) / 72000 + 2;
  1889.         /* 72 = opt X den */
  1890.     fontNode->fn_MaxModulo = ((fontNode->fn_MaxWidth + 15) >> 3) & ~1;
  1891.     fontNode->fn_MaxCharLength = fontNode->fn_MaxModulo * fontNode->fn_FontSize;
  1892.     fontNode->fn_MaxFontLength = fontNode->fn_BaseLength + fontNode->fn_MaxCharLength + 2 + 76;
  1893.  
  1894.     /* This time: use AllocMem because this might be a diskfont seglist */
  1895.     extDFHeader = (struct ExtDFHeader *)AllocMem((fontNode->fn_MaxFontLength), (MEMF_PUBLIC | MEMF_CLEAR));
  1896.     if (extDFHeader == 0)
  1897.     {
  1898.         PSTrace("%%Cannot get memory for new TextFont\n");
  1899.         psError = -1;
  1900.         return(0);
  1901.     }
  1902.     fontNode->fn_ExtDFHeader = extDFHeader;
  1903.     extDFHeader->edf_Length = fontNode->fn_MaxFontLength;
  1904.     /* Fill dfHeader up */
  1905.     extDFHeader->edf_DFHeader.dfh_DF.ln_Name = extDFHeader->edf_DFHeader.dfh_Name;
  1906.     extDFHeader->edf_DFHeader.dfh_FileID = DFH_ID;
  1907.     /* seglist pointer one longword ahead of the extDFHeader */
  1908.     extDFHeader->edf_DFHeader.dfh_Segment = MKBADDR((ULONG)extDFHeader + 4);
  1909.     extDFHeader->edf_DFHeader.dfh_Revision = 1;
  1910.     /* Continue filling TextFont struct */
  1911.     newFont = &extDFHeader->edf_DFHeader.dfh_TF;
  1912.     fontNode->fn_CharLoc =        (short *)&newFont[1];
  1913.     fontNode->fn_CharSpace =     (short *)&fontNode->fn_CharLoc[(fontNode->fn_HighChar - fontNode->fn_LowChar + 2) * 2];
  1914.     fontNode->fn_CharKern =        (short *)&fontNode->fn_CharSpace[fontNode->fn_HighChar - fontNode->fn_LowChar + 2];
  1915.     fontNode->fn_CharData =     (char  *)&fontNode->fn_CharKern[fontNode->fn_HighChar - fontNode->fn_LowChar + 2];
  1916.     fontNode->fn_CharFontName =     (char  *)extDFHeader->edf_DFHeader.dfh_Name;
  1917. //    fontNode->fn_CharFontName =     (char  *)&fontNode->fn_CharData[fontNode->fn_MaxCharLength];
  1918.     strcpy(fontNode->fn_CharFontName, textAttr->ta_Name);
  1919.     PSTrace("TextFont pointers:   Font at    %8X\n", newFont);
  1920.     PSTrace("                     Loc at     %8X\n", fontNode->fn_CharLoc);
  1921.     PSTrace("                     Space at   %8X\n", fontNode->fn_CharSpace);
  1922.     PSTrace("                     Kern at    %8X\n", fontNode->fn_CharKern);
  1923.     PSTrace("                     Data at    %8X\n", fontNode->fn_CharData);
  1924.     PSTrace("                     Name at    %8X\n", fontNode->fn_CharFontName);
  1925.     PSTrace("                     Name is %s\n", fontNode->fn_CharFontName);
  1926.  
  1927.     /* Prepare remaining TextFont attributes */
  1928.     newFont->tf_Message.mn_Node.ln_Name = fontNode->fn_CharFontName;
  1929.     newFont->tf_Message.mn_Node.ln_Type = NT_FONT;
  1930.     newFont->tf_Message.mn_Length = fontNode->fn_MaxFontLength + 64;
  1931.     newFont->tf_YSize = textAttr->ta_YSize;
  1932.     newFont->tf_Style = fontNode->fn_Style;
  1933.     newFont->tf_Flags = (FPF_DISKFONT | FPF_PROPORTIONAL | FPF_DESIGNED);
  1934.     fontNode->fn_BaseLine = (textAttr->ta_YSize * fontNode->fn_OptBaseLine + 500) / 1000;
  1935.     if (fontNode->fn_BaseLine < 0)
  1936.         fontNode->fn_BaseLine = 0;
  1937.     if (fontNode->fn_BaseLine > textAttr->ta_YSize)
  1938.         fontNode->fn_BaseLine = textAttr->ta_YSize - 1;
  1939.     newFont->tf_Baseline = textAttr->ta_YSize - fontNode->fn_BaseLine - 1;
  1940.     newFont->tf_BoldSmear = textAttr->ta_YSize / 20 + 1;
  1941.     newFont->tf_LoChar = fontNode->fn_LowChar;
  1942.     newFont->tf_HiChar = fontNode->fn_HighChar;
  1943.     newFont->tf_Modulo = fontNode->fn_MaxModulo;
  1944.     newFont->tf_CharLoc = (APTR)fontNode->fn_CharLoc;
  1945.     newFont->tf_CharSpace = (APTR)fontNode->fn_CharSpace;
  1946.     newFont->tf_CharKern = (APTR)fontNode->fn_CharKern;
  1947.     newFont->tf_CharData = (APTR)fontNode->fn_CharData;
  1948.  
  1949.     /* Prepare additional values in fontNode struct */
  1950.     fontNode->fn_ActWidth = 0;
  1951.     fontNode->fn_NomWidth = 0;
  1952.     fontNode->fn_NomCount = 0;
  1953.     fontNode->fn_CharPosX = 0;
  1954.  
  1955.     /* Right here should be the end of MakeATEFont() except for tf_CharSpace */
  1956.     /* and tf_CharKern array generation.  The rest will move to MakeATEChars() */
  1957.     /* And it has.  This part just pre-builds the font shell */
  1958.  
  1959.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index ++)
  1960.     {
  1961.         z1 = (fontNode->fn_LowLeftX[index] * fontNode->fn_FontSize * fontNode->fn_XDPI - 41000) / 72000;
  1962.             /* opt x den */
  1963.         z2 = (fontNode->fn_UpRightX[index] * fontNode->fn_FontSize * fontNode->fn_XDPI + 41000) / 72000;
  1964.             /* opt x den */
  1965.         if (z1 < 0)
  1966.             zZ = z2 - z1;
  1967.         else
  1968.             zZ = z2 + z1;
  1969.         fontNode->fn_CharLoc[(index - fontNode->fn_LowChar) * 2 + 1] = zZ;
  1970.         fontNode->fn_CharSpace[(index - fontNode->fn_LowChar)] = -z1 + (fontNode->fn_CharWidths[index] * fontNode->fn_FontSize * fontNode->fn_XDPI + 41000) / 72000;
  1971.         fontNode->fn_CharKern[(index - fontNode->fn_LowChar)] = z1;
  1972.         if (fontNode->fn_LowLeftY[index] != fontNode->fn_UpRightY[index])
  1973.         {
  1974.             fontNode->fn_NomWidth += (zZ * 1.3);
  1975.             fontNode->fn_NomCount++;
  1976.         }
  1977.     }
  1978.  
  1979.     /* Some extra parts of the TextFont struct missed above */
  1980.     newFont->tf_XSize = fontNode->fn_NomWidth / (fontNode->fn_HighChar - fontNode->fn_LowChar);
  1981.     /* Reset position ptr for char drawing */
  1982.     /* OK, finally the new TextFont is ready for use (maybe...) */
  1983.     if (psError != 0)
  1984.     {
  1985.         FreeMem(extDFHeader, fontNode->fn_MaxFontLength);
  1986.         return(0);
  1987.     }
  1988.  
  1989.     return(newFont);        
  1990. }
  1991.  
  1992. /* MakeATEChars() searches fn_BuiltChars and builds characters flagged with */
  1993. /* CHAR_NEEDED, then sets the value to CHAR_DRAWN.  */
  1994. BOOL MakeATEChars(struct FontNode *fontNode)
  1995. {
  1996.     int        index, z1, z2, zZ;
  1997. //    int        y1, y2;
  1998. struct    TextFont    *newFont = fontNode->fn_TextFont;
  1999. //structPSdevice    *localPage = &psParm->page;
  2000.  
  2001.     /* Check for blacklisting */
  2002.     if (fontNode->fn_BlackList == TRUE)
  2003.         return(FALSE);
  2004.  
  2005.     /* Prepare page area for the new chars */
  2006.     psParm->page.buf[0] = newFont->tf_CharData;
  2007.     psParm->page.len = fontNode->fn_MaxCharLength;
  2008.     psParm->page.depth = 1;
  2009.     psParm->page.xbytes = fontNode->fn_MaxModulo;
  2010.     psParm->page.xsize = fontNode->fn_MaxWidth;
  2011.     psParm->page.ysize = fontNode->fn_FontSize;
  2012.     psParm->page.yheight = fontNode->fn_FontSize;
  2013.  
  2014.     /* Beginning of MakeATEChars() (Fingers crossed) */
  2015.     PSsetdevice(psActivation, &psParm->page);
  2016.  
  2017.     /* OK, draw some characters. */
  2018.     /* first re-load the typeface needed... */
  2019. //    PSIntf("/fontname /%.100s def\n", fontNode->fn_TypefaceName);
  2020. //    PSIntf("fontname findfont pop\n");
  2021. //    PSIntf("/font fontname .findfont def\n");
  2022.  
  2023.     PSIntf("/font /%.100s findfont def\n", fontNode->fn_TypefaceName);
  2024.  
  2025.     PSIntf("/newfont font maxlength dict def\n");
  2026.     PSIntf(    "font\n"
  2027.         "{ exch dup /FID ne"
  2028.         "{ exch newfont 3 1 roll put } { pop pop } ifelse }\n"
  2029.         "forall\n");
  2030.     if (fontNode->fn_OptFontEncoding == 'S')
  2031.         PSIntf("newfont /Encoding encoding put\n");
  2032.     PSIntf("/_%.100s newfont definefont pop\n", fontNode->fn_TypefaceName);
  2033.  
  2034.     /* ... then initmatrix the drawing area and start drawing */
  2035.     PSIntf("initmatrix\n");
  2036.     PSIntf("/xscale %d %d mul 72 div def\n", newFont->tf_YSize, fontNode->fn_XDPI);
  2037.         /* 72 = optXDen */
  2038.     PSIntf("/yscale %d %d mul 72 div def\n", newFont->tf_YSize, defaultDPI);
  2039.         /* 72 = optYDen */
  2040.     PSIntf("newfont [ xscale 0 0 yscale 0 0 ] makefont setfont\n");
  2041.  
  2042.     /* Character loop.  MakeATEChars() keeps a running position ptr and fills */
  2043.     /* the CharLoc and CharKern arrays along with the CharData bitmap. */
  2044.     /* Since the Amiga uses the position ptrs in tf_CharLoc the chars can */
  2045.     /* render in any order. */
  2046.     for (index = fontNode->fn_LowChar; index <= fontNode->fn_HighChar; index ++)
  2047.     {
  2048.         if (fontNode->fn_BuiltChars[index] == CHAR_NEEDED)
  2049.         {
  2050.             z1 = (fontNode->fn_LowLeftX[index] * fontNode->fn_FontSize * fontNode->fn_XDPI - 41000) / 72000;
  2051.                 /* opt x den */
  2052.             z2 = (fontNode->fn_UpRightX[index] * fontNode->fn_FontSize * fontNode->fn_XDPI + 41000) / 72000;
  2053.                 /* opt x den */
  2054.             if (z1 < 0)
  2055.                 zZ = z2 - z1;
  2056.             else
  2057.                 zZ = z2 + z1;
  2058.             PSIntf("cstr 0 %d put\n", index);
  2059.             PSIntf("%d %d moveto ", fontNode->fn_ActWidth - z1, fontNode->fn_BaseLine);
  2060.             /* reference to optxden in y1 was here */
  2061.             PSIntf("cstr show\n");
  2062.             if (psError != 0)
  2063.             {
  2064.                 PSTrace("PostScript error drawing character %d %c\n", index, index);
  2065.                 break;
  2066.             }
  2067.             fontNode->fn_CharLoc[(index - fontNode->fn_LowChar) * 2] = fontNode->fn_ActWidth;
  2068.             fontNode->fn_ActWidth += (zZ * 1.3);
  2069.             fontNode->fn_BuiltChars[index] = CHAR_DRAWN;
  2070.         }
  2071.     }
  2072.     if (psError != 0)
  2073.         fontNode->fn_BlackList = TRUE;
  2074.  
  2075.     /* I really don't expect any non-PS errors here so just return(TRUE). */
  2076.     /* The font already exists and there's enough memory by this point. */
  2077.     return(TRUE);
  2078. }
  2079.  
  2080. /* Unloads all unused ATE fonts and fontnodes */
  2081. void ClearUnusedATEFonts(struct FontList *fontList)
  2082. {
  2083. struct    SignalSemaphore        *listSemaphore = &ateFontList->ateSemaphore;
  2084. struct    List            *localFontList = &ateFontList->fontList;
  2085. struct    FontNode        *workNode, *nextNode, *tempNode;
  2086.     BOOL            killFont;
  2087.     char            workName[64];
  2088.  
  2089.     /* Get access to the list */
  2090.     ObtainSemaphore(listSemaphore);
  2091.  
  2092.     /* If the list is empty to begin with, exit */
  2093.     if (localFontList->lh_Head->ln_Succ == 0)
  2094.     {
  2095.         ReleaseSemaphore(listSemaphore);
  2096.         return();
  2097.     }
  2098.  
  2099.     /* Begin traversing the font list */
  2100.     workNode = (struct FontNode *)localFontList->lh_Head;
  2101.  
  2102.     for (workNode = (struct FontNode *)localFontList->lh_Head;
  2103.          workNode->fn_Node.ln_Succ; )
  2104.     {
  2105.         nextNode = (struct FontNode *)workNode->fn_Node.ln_Succ;
  2106.  
  2107.         killFont = FALSE;
  2108.  
  2109.         if (workNode->fn_BlackList == TRUE)
  2110.             killFont = TRUE;
  2111.         else if (workNode->fn_TextFont->tf_Accessors == 0)
  2112.         {
  2113.             /* if this is a styled font, make sure this isn't
  2114.                used through SetSoftStyle() */
  2115.             if (workNode->fn_Style != FS_NORMAL)
  2116.             {
  2117.                 sprintf(workName, "%50s / %5d / %2x",
  2118.                     workNode->fn_TextFont->tf_Message.mn_Node.ln_Name,
  2119.                     workNode->fn_FontSize, FS_NORMAL);
  2120.                 tempNode = (struct FontNode *)FindName(localFontList, workName);
  2121.                 if (tempNode != 0)
  2122.                 {
  2123.                     /* So it is used via SetSoftStyle...
  2124.                        check its count */
  2125.                     if (tempNode->fn_TextFont->tf_Accessors == 0)
  2126.                         killFont = TRUE;
  2127.                 }
  2128.                 else
  2129.                     killFont = TRUE;
  2130.             }
  2131.             else
  2132.                 killFont = TRUE;
  2133.         }
  2134.         tempNode = workNode;
  2135.         workNode = (struct FontNode *)workNode->fn_Node.ln_Succ;
  2136.  
  2137.         /* If killFont was set, remove it and the node */
  2138.         if (killFont == TRUE)
  2139.         {
  2140.             if (tempNode->fn_TextFont != 0)
  2141.             {
  2142.                 RemFont(tempNode->fn_TextFont);
  2143.                 StripFont(tempNode->fn_TextFont);
  2144.                 FreeMem(tempNode->fn_ExtDFHeader, tempNode->fn_ExtDFHeader->edf_Length);
  2145. //                FreeVec(tempNode->fn_TextFont);
  2146.             }
  2147.             Remove((struct Node *)tempNode);
  2148.             FreeVec(tempNode);
  2149.         }
  2150.     }
  2151.     ReleaseSemaphore(listSemaphore);
  2152.  
  2153.     /* "Re-boot" the PS interpreter */
  2154.     PSdeleteact(psActivation);
  2155.  
  2156.     /* re-initalize the PostScript activation */
  2157.     PSTrace("%%Re-initalizing PostScript Activation\n");
  2158.     psParm->page.buf[0] = nameBuffer;
  2159.     psParm->page.len = 100;
  2160.     psParm->page.depth = 1;
  2161.     psParm->page.xbytes = 10;
  2162.     psParm->page.xsize = 80;
  2163.     psParm->page.ysize = 10;
  2164.     psParm->page.xden = 72;
  2165.     psParm->page.yden = 72;
  2166.     psParm->page.ydir = -1;
  2167.     psParm->memvlen = 20000;
  2168.     psParm->memflen = 10000;
  2169.     psParm->memllen = defmemllen;
  2170.     psParm->memhlen = minmemhlen;
  2171.  
  2172.     psActivation = PScreateact(psParm);
  2173.  
  2174.     /* Run ATE startup files */
  2175.     PSTrace("%%All initalization passed, re-running PS startup & encoding files\n");
  2176.     PSIntf("(%.100s) run clear\n", "PSFonts:init.ps");
  2177.     PSIntf("/encoding StandardEncoding 256 array copy def\n");
  2178.     PSIntf("[ (%.100s) run] aload length 2 idiv\n", "PSFonts:ATEencoding.ps");
  2179.     PSIntf("{ encoding 3 1 roll put } repeat\n");
  2180.     PSIntf("/cstr 1 string def\n");
  2181.  
  2182.     return;
  2183. }
  2184.  
  2185. /* Fcn that counts the opencount in each ATE font */
  2186. int CountOpenFonts(void)
  2187. {
  2188. struct    TextFont    *currentFont, *nextFont;
  2189.     int        openCount;
  2190. struct    TextAttr    topazAttr;
  2191.  
  2192.     topazAttr.ta_Name = "topaz.font";
  2193.     topazAttr.ta_YSize = 8;
  2194.     topazAttr.ta_Style = FS_NORMAL;
  2195.     topazAttr.ta_Flags = 0;
  2196.  
  2197.     openCount = 0;
  2198.  
  2199.     /* Start by obtaining topaz.8, the first font in the system list */
  2200.     currentFont = (struct TextFont *)OpenFont(&topazAttr);
  2201.     CloseFont(currentFont);
  2202.  
  2203.     /* Now go into a Forbid() state and check the list */
  2204.     Forbid();
  2205.     nextFont = (struct TextFont *)currentFont->tf_Message.mn_Node.ln_Succ;
  2206.     while (nextFont != 0)
  2207.     {
  2208.         if (memcmp(currentFont->tf_Message.mn_Node.ln_Name, "_ATE_", 5) == 0)
  2209.         {
  2210.             openCount = openCount + currentFont->tf_Accessors;
  2211.         }
  2212.         currentFont = nextFont;
  2213.         nextFont = (struct TextFont *)currentFont->tf_Message.mn_Node.ln_Succ;
  2214.     }
  2215.     Permit();
  2216.  
  2217.     return(openCount);
  2218. }
  2219.  
  2220. /* Fcn which builds ATEAvailFonts struct */
  2221. struct ATEAvailFonts *PrepATEAvailFonts(int sizeMax, int sizeInc, int diskfontSize)
  2222. {
  2223. struct    ATEAvailFonts        *tempATEAvailFonts;
  2224.     BOOL            executeSuccess;
  2225.     FILE            *ateListFile;
  2226.     char            readLine[100], charName[32], *afATEFontNames;
  2227.     int            asciiValue, afATEFonts, numAteSizes, numAteNames;
  2228.     int            newSizeMax, remainderTest;
  2229.     int            index;
  2230.  
  2231.     /* Check and decrease sizeMax as necessary */
  2232.     numAteSizes = sizeMax / sizeInc;
  2233.     remainderTest = numAteSizes * sizeInc;
  2234.     if (remainderTest == sizeMax)
  2235.         newSizeMax = sizeMax;
  2236.     else
  2237.         newSizeMax = remainderTest;
  2238.     if (newSizeMax <= sizeInc || sizeInc == 0)
  2239.     {
  2240.         fprintf(ateOutput, "You goofed over here\n");
  2241.         fflush(ateOutput);
  2242.         return(0);
  2243.     }
  2244.  
  2245.     /* Generate list file in T: */
  2246.     executeSuccess = Execute("List FONTS:_ATE_#? <NIL: >T:ateFonts.ate", 0, 0);
  2247.     if (executeSuccess == FALSE)
  2248.     {
  2249.         fprintf(ateOutput, "Some stupid goofup gathering ATE fonts happened.\n"
  2250.                    "Make sure you have the List command in your system.\n");
  2251.         fflush(ateOutput);
  2252.         return(0);
  2253.     }
  2254.     ateListFile = fopen("T:ateFonts.ate", "r");
  2255.     if (ateListFile == 0)
  2256.     {
  2257.         fprintf(ateOutput, "This isn't supposed to happen; make sure you have T: assigned.\n");
  2258.         fflush(ateOutput);
  2259.         return(0);
  2260.     }
  2261.     fgets(readLine, 100, ateListFile);    /* skip first line */
  2262.     while (!feof(ateListFile))
  2263.     {
  2264.         asciiValue = 0;
  2265.         numAteNames = 0;
  2266.         charName[0] = 0;
  2267.         readLine[0] = 0;
  2268.         fgets(readLine, 100, ateListFile);
  2269.         sscanf(readLine, "%d files - %d blocks used", &numAteNames, &asciiValue);
  2270.         if (numAteNames != 0)
  2271.             break;
  2272.     }
  2273.     if (feof(ateListFile) && numAteNames == 0)
  2274.     {
  2275.         fprintf(ateOutput, "You don't have any _ATE_ files in FONTS:.\n"
  2276.                    "Run ATE Control Panel to install them.\n");
  2277.         fflush(ateOutput);
  2278.         fclose(ateListFile);
  2279.         return(0);
  2280.     }
  2281.     fclose(ateListFile);
  2282.  
  2283.     /* ATEAvailFonts struct */
  2284.     tempATEAvailFonts = (struct ATEAvailFonts *)AllocVec(sizeof(struct ATEAvailFonts)
  2285.                             + numAteNames * 32,
  2286.                             MEMF_PUBLIC | MEMF_CLEAR);
  2287.     if (tempATEAvailFonts == 0)
  2288.     {
  2289.         fprintf(ateOutput, "Not enough memory to get AvailFonts struct\n"
  2290.                    "in place, probably not enough memory to run ATE.\n");
  2291.         fflush(ateOutput);
  2292.         return(0);
  2293.     }
  2294.  
  2295.     /* Fill out contents of ATEAvailFonts struct */
  2296.     afATEFonts = numAteNames * numAteSizes * sizeof(struct TAvailFonts);
  2297.     tempATEAvailFonts->aaf_SizeDiskFonts = diskfontSize;
  2298.     tempATEAvailFonts->aaf_SizeATEFonts =  afATEFonts;
  2299.     tempATEAvailFonts->aaf_SizeATEData = numAteNames * 32 + sizeof(struct TagItem) * 2;
  2300.     tempATEAvailFonts->aaf_ATETags[0].ti_Tag = TA_DeviceDPI;
  2301.     tempATEAvailFonts->aaf_ATETags[0].ti_Data = 0x00010000 * defaultDPI + defaultDPI;
  2302.     tempATEAvailFonts->aaf_ATETags[1].ti_Tag = TAG_END;
  2303.     tempATEAvailFonts->aaf_ATETags[1].ti_Data = 0;
  2304.     /* Now build all the fontname list (Oh joy) at least it should work */
  2305.     tempATEAvailFonts->aaf_FontNames = (char *)&tempATEAvailFonts[1];/* Right after struct */
  2306.     tempATEAvailFonts->aaf_NumNames = numAteNames;
  2307.     tempATEAvailFonts->aaf_SizeATEData = sizeof(struct TagItem) * 2 + numAteNames * 32;
  2308.     afATEFontNames = tempATEAvailFonts->aaf_FontNames;
  2309.     ateListFile = fopen("T:ateFonts.ate", "r");
  2310.     /* Skip the first line */
  2311.     fgets(readLine, 100, ateListFile);
  2312.     for (index = 0; index < numAteNames; index++)
  2313.     {
  2314.         readLine[0] = 0;
  2315.         charName[0] = 0;
  2316.         fgets(readLine, 100, ateListFile);
  2317.         sscanf(readLine, "%s ", charName);
  2318.         if (charName[0] != 0)
  2319.         {
  2320.             strcpy(&afATEFontNames[index * 32], charName);
  2321.             strcat(&afATEFontNames[index * 32], ".font");
  2322.         }
  2323.     }
  2324.     fclose(ateListFile);
  2325.     tempATEAvailFonts->aaf_SizeInc = sizeInc;
  2326.     tempATEAvailFonts->aaf_SizeMax = newSizeMax;
  2327.  
  2328.     return(tempATEAvailFonts);
  2329. }
  2330.  
  2331. /* Nice function for PS tracing */
  2332. void PSTrace(char *format, ...)
  2333. {
  2334.     va_list    ap;
  2335.  
  2336.     if (optTrace == TRUE)
  2337.     {
  2338.         va_start(ap, format);
  2339.         vfprintf(ateOutput, format, ap);
  2340.         fflush(ateOutput);
  2341.         va_end(ap);
  2342.     }
  2343.     return;
  2344. }
  2345.  
  2346. /* Nice function for PS command tracing too */
  2347. void PSIntf(char *format, ...)
  2348. {
  2349.     va_list    ap;
  2350.     char    psString[200];
  2351.  
  2352.     if (psError != 0)
  2353.         return;
  2354.  
  2355.     va_start(ap, format);
  2356.     if (optDebug == TRUE)
  2357.     {
  2358.         vfprintf(ateOutput, format, ap);
  2359.         fflush(ateOutput);
  2360.     }
  2361.     vsprintf(psString, format, ap);
  2362.     psError = PSintstring(psActivation, psString, -1, PSFLAGSTRING);
  2363.     va_end(ap);
  2364.     return;
  2365. }
  2366.  
  2367. __geta4 __regargs ULONG NewDFbaseExpunge(__A6 struct Library *libBase)
  2368. {
  2369.     ULONG        tempResult;
  2370.  
  2371.     tempResult = OldDFbaseExpunge(libBase);
  2372.     /* This gives a PS re-start a better chance */
  2373.  
  2374.     /* Signal the main task to unload unused stuff */
  2375.     Signal(ateMainTask, 1 << ateDfeSigBit);
  2376.  
  2377.     return(tempResult);
  2378. }
  2379.  
  2380. __geta4 __regargs struct TextFont *NewOpenDiskFont(__A0 struct TextAttr *textAttr, __A6 struct Library *libBase)
  2381. {
  2382. struct    DiskfontMsg    *diskFontMsg;
  2383. struct    TextFont    *tempTextFont;
  2384. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  2385. struct    List        *fontList = &ateFontList->fontList;
  2386. struct    FontNode    *fontNode;
  2387.     char        *searchString;
  2388.     BOOL        msgSent;
  2389.     BOOL        ateFont;
  2390.  
  2391.     diskFontMsg = (struct DiskFontMsg *)AllocVec(sizeof(struct DiskfontMsg) + 64, MEMF_PUBLIC | MEMF_CLEAR);
  2392.     if (diskFontMsg != 0)
  2393.     {
  2394.         /* Search for existing font in node first */
  2395.         searchString = (char *)&diskFontMsg[1];
  2396.         sprintf(searchString, "%50s / %5d / %2x", textAttr->ta_Name, textAttr->ta_YSize, (textAttr->ta_Style & (FSF_BOLD | FSF_ITALIC)));
  2397.         ObtainSemaphoreShared(ateSemaphore);
  2398.         fontNode = (struct FontNode *)FindName(fontList, searchString);
  2399.         ReleaseSemaphore(ateSemaphore);
  2400.         if (fontNode == 0)
  2401.         {
  2402.             /* Prepare message for sending */
  2403.             diskFontMsg->df_ATEMsg.ate_MsgLength = sizeof(struct DiskfontMsg);
  2404.             diskFontMsg->df_ATEMsg.ate_DestPort = ateODFPort;
  2405.             diskFontMsg->df_TextAttr = textAttr;
  2406.             diskFontMsg->df_TextFont = 0;
  2407.             /* send message */
  2408.             msgSent = ATESendMsg((struct ATEMessage *)diskFontMsg);
  2409.             ateFont = diskFontMsg->df_ATEFont;
  2410.             tempTextFont = diskFontMsg->df_TextFont;
  2411.         }
  2412.         FreeVec(diskFontMsg);
  2413.     }
  2414.     tempTextFont = OldOpenDiskFont(textAttr, libBase);
  2415.     return(tempTextFont);
  2416. }
  2417.  
  2418. /* New patch for NewScaledDiskFont() */
  2419. __geta4 __regargs struct DiskFontHeader *NewNSDF(__A0 struct TextFont *textFont, __A1 struct TextAttr *textAttr, __A6 struct Library *libBase)
  2420. {
  2421.     char        *fontName;
  2422. struct    DiskFontHeader    *dfHeader;
  2423. struct    NsdfMsg        *nsdfMsg;
  2424.     BOOL        msgSent;
  2425.  
  2426.     fontName = textFont->tf_Message.mn_Node.ln_Name;
  2427.     if (memcmp(fontName, "_ATE_", 5) == 0)
  2428.     {
  2429.         nsdfMsg = (struct NsdfMsg *)AllocVec(sizeof(struct NsdfMsg), MEMF_PUBLIC | MEMF_CLEAR);
  2430.         if (nsdfMsg != 0)
  2431.         {
  2432.             nsdfMsg->nsdf_ATEMsg.ate_MsgLength = sizeof(struct NsdfMsg);
  2433.             nsdfMsg->nsdf_ATEMsg.ate_DestPort = ateNSDFPort;
  2434.             nsdfMsg->nsdf_TextAttr = textAttr;
  2435.             nsdfMsg->nsdf_TextFont = textFont;
  2436.             nsdfMsg->nsdf_DFHeader = 0;
  2437.             /* send message */
  2438.             msgSent = ATESendMsg((struct ATEMessage *)nsdfMsg);
  2439.             dfHeader = nsdfMsg->nsdf_DFHeader;
  2440.         }
  2441.     }
  2442.     else
  2443.         dfHeader = OldNSDF(textFont, textAttr, libBase);
  2444.     
  2445.     return(dfHeader);
  2446.  
  2447. }
  2448.  
  2449. __geta4 __regargs void NewText(__A1 struct RastPort *rastPort, __A0 STRPTR textString, __D0 WORD length, __A6 struct Library *libBase)
  2450. {
  2451. struct    TextMsg        *textMsg;
  2452. struct    FontNode    *fontNode;
  2453. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  2454. struct    List        *fontList = &ateFontList->fontList;
  2455.     BOOL        msgSent;
  2456.     char        *searchString;
  2457.     BOOL        softStyleMode = FALSE;
  2458.     BOOL        localOptSoftStyles = optSoftStyles;
  2459.     UBYTE        ateStyle = FS_NORMAL;
  2460.     UBYTE        ssModeOldStyle = rastPort->AlgoStyle;
  2461. struct    TextFont    *ssModeOldFont = rastPort->Font;
  2462.  
  2463.     textMsg = (struct TextMsg *)AllocVec(sizeof(struct TextMsg) + 64, (MEMF_PUBLIC | MEMF_CLEAR));
  2464.     if (textMsg != 0)
  2465.     {
  2466.         /* Check if SetSoftStyle was blatantly used */
  2467.         ateStyle = ssModeOldStyle & (FSF_BOLD | FSF_ITALIC);
  2468.         if (ateStyle != FS_NORMAL)
  2469.             softStyleMode = TRUE;
  2470.  
  2471.         searchString = (char *)&textMsg[1];
  2472.         /* find the fontNode */
  2473.         if (softStyleMode == TRUE)
  2474.             sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, ateStyle);
  2475.         else
  2476.             sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, rastPort->Font->tf_Style);
  2477.         ObtainSemaphoreShared(ateSemaphore);
  2478.         fontNode = (struct FontNode *)FindName(fontList, searchString);
  2479.         ReleaseSemaphore(ateSemaphore);
  2480.  
  2481.         if (softStyleMode == TRUE && fontNode != 0)
  2482.         {
  2483.             if (fontNode->fn_BlackList == FALSE)
  2484.             {
  2485.                 SetFont(rastPort, fontNode->fn_TextFont);
  2486.                 OldSSStyle(rastPort, ssModeOldStyle ^ ateStyle,
  2487.                        FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED, gfxBase);
  2488.             }
  2489.             else
  2490.                 fontNode = 0;
  2491.         }
  2492.         if (fontNode == 0)
  2493.         {
  2494.             /* Repeat search for normal style */
  2495.             sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, FS_NORMAL);
  2496.             ObtainSemaphoreShared(ateSemaphore);
  2497.             fontNode = (struct FontNode *)FindName(fontList, searchString);
  2498.             ReleaseSemaphore(ateSemaphore);
  2499.             /* If this was an ATE font without styles, cancel SoftStyle mode */
  2500.             if (fontNode != 0)
  2501.             {
  2502.                 softStyleMode = FALSE;
  2503.                 /* If soft styles aren't allowed on ATE fonts, change it */
  2504.                 if (localOptSoftStyles == FALSE)
  2505.                     rastPort->AlgoStyle = ssModeOldStyle ^ ateStyle;
  2506.             }
  2507.         }
  2508.         if (fontNode != 0)
  2509.         {
  2510.             if (fontNode->fn_BlackList == FALSE)
  2511.             {
  2512.                 /* Prepare TextMsg struct for use */
  2513.                 textMsg->tm_ATEMsg.ate_DestPort = ateTextPort;
  2514.                 textMsg->tm_ATEMsg.ate_MsgLength = sizeof(struct TextMsg);
  2515.                 textMsg->tm_RastPort = rastPort;
  2516.                 textMsg->tm_FontNode = fontNode;
  2517.                 textMsg->tm_Chars = textString;
  2518.                 textMsg->tm_Length = length;
  2519.                 /* send the message */
  2520.                 msgSent = ATESendMsg((struct ATEMessage *)textMsg);
  2521.             }
  2522.         }
  2523.         FreeVec(textMsg);
  2524.     }
  2525.  
  2526.     OldText(rastPort, textString, length, libBase);
  2527.  
  2528.     if (softStyleMode == TRUE && fontNode != 0)
  2529.     {
  2530.         SetFont(rastPort, ssModeOldFont);
  2531.         OldSSStyle(rastPort, ssModeOldStyle ^ ateStyle,
  2532.                FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED, gfxBase);
  2533.     }
  2534.     if (localOptSoftStyles == FALSE && softStyleMode == FALSE && fontNode != 0)
  2535.         OldSSStyle(rastPort, ssModeOldStyle ^ ateStyle,
  2536.                FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED, gfxBase);
  2537.  
  2538.     return;
  2539. }
  2540.  
  2541. /* Various patches for TextLength, TextExtent, and TextFit
  2542.  
  2543. __geta4 __regargs WORD NewTextLength(__A1 struct RastPort *rastPort, __A0 STRPTR aString, __D0 WORD strCount, __A6 struct Library *libBase)
  2544. {
  2545.     WORD        textLength;
  2546. struct    FontNode    *fontNode;
  2547. struct    TextFont    *oldTextFont = rastPort->Font;
  2548.     UBYTE        oldStyle = rastPort->AlgoStyle;
  2549.  
  2550.     fontNode = SwapSoftStyle(rastPort);
  2551.     
  2552.     textLength = OldTextLength(rastPort, aString, strCount, libBase);
  2553.  
  2554.     if (fontNode != 0)
  2555.         UndoSwapSoftStyle(rastPort, oldTextFont, oldStyle);
  2556.  
  2557.     return(textLength);
  2558. }
  2559.  
  2560. __geta4 __regargs struct TextExtent *NewTextExtent(__A1 struct RastPort *rastPort, __A0 STRPTR aString, __D0 WORD strCount, __A2 struct TextExtent *tExtent)
  2561. {
  2562. struct    TextExtent    *destTextExtent;
  2563. struct    FontNode    *fontNode;
  2564. struct    TextFont    *oldTextFont = rastPort->Font;
  2565.     UBYTE        oldStyle = rastPort->AlgoStyle;
  2566.  
  2567.     fontNode = SwapSoftStyle(rastPort);
  2568.     
  2569.     destTextExtent = OldTextExtent(rastPort, aString, strCount, tExtent, gfxBase);
  2570.  
  2571.     if (fontNode != 0)
  2572.         UndoSwapSoftStyle(rastPort, oldTextFont, oldStyle);
  2573.  
  2574.     return(destTextExtent);
  2575. } */
  2576.  
  2577. /* Unlike the previous patches, this patch needs a bit more intelligence.
  2578.    As such, the server will pass back a new TextFont ptr and style bits
  2579.    not yet set (such as FSF_UNDERLINED) so the patch can still set a 
  2580.    software style as required.  This will then SetFont() the font passed
  2581.    back and SetSoftStyle() any missing styles.
  2582.  
  2583.    Oops.  Because some programs work in mysterious ways, I SetFont() the
  2584.    styled fonts in the Text() patch now, instead. */
  2585. __geta4 __regargs ULONG NewSSStyle(__A1 struct RastPort *rastPort, __D0 ULONG newStyle, __D1 ULONG enable, __A6 struct Library *libBase)
  2586. {
  2587. struct    SSStyleMsg    *sssMsg;
  2588. struct    FontNode    *fontNode;
  2589. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  2590. struct    List        *fontList = &ateFontList->fontList;
  2591.     ULONG        stylesNeeded = newStyle;
  2592.     ULONG        resultingStyle;
  2593.     ULONG        ateStyle;
  2594.     BOOL        msgSent;
  2595.     char        *searchString;
  2596.  
  2597.     ateStyle = newStyle & enable & (FSF_BOLD | FSF_ITALIC);
  2598.     if (ateStyle != FS_NORMAL)
  2599.     {
  2600.         sssMsg = (struct SSStyleMsg *)AllocVec(sizeof(struct SSStyleMsg) + 64, (MEMF_PUBLIC | MEMF_CLEAR));
  2601.         if (sssMsg != 0)
  2602.         {
  2603.             /* Search through list for existing style first */
  2604.             searchString = (char *)&sssMsg[1];
  2605.             sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, ateStyle);
  2606.             ObtainSemaphoreShared(ateSemaphore);
  2607.             fontNode = (struct FontNode *)FindName(fontList, searchString);
  2608.             ReleaseSemaphore(ateSemaphore);
  2609.             if (fontNode == 0)
  2610.             {
  2611.                 /* Check for ATE normal style */
  2612.                 sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, FS_NORMAL);
  2613.                 ObtainSemaphoreShared(ateSemaphore);
  2614.                 fontNode = (struct FontNode *)FindName(fontList, searchString);
  2615.                 ReleaseSemaphore(ateSemaphore);
  2616.                 if (fontNode != 0)
  2617.                 {
  2618.                     /* prepare message struct */
  2619.                     sssMsg->ss_ATEMsg.ate_DestPort = ateSSSPort;
  2620.                     sssMsg->ss_ATEMsg.ate_MsgLength = sizeof(struct SSStyleMsg);
  2621.                     sssMsg->ss_RastPort = rastPort;
  2622.                     sssMsg->ss_FontNode = fontNode;
  2623.                     sssMsg->ss_NewStyle = newStyle;
  2624.                     sssMsg->ss_Enable = enable;
  2625.                     sssMsg->ss_SoftStyleNeeded = newStyle;
  2626.                     /* Send the message */
  2627.                     msgSent = ATESendMsg((struct ATEMessage *)sssMsg);
  2628.                 }
  2629.             }
  2630.             FreeVec(sssMsg);
  2631.         }
  2632.     }
  2633.  
  2634.     /* Call original function to complete any needed style change */
  2635.     resultingStyle = OldSSStyle(rastPort, newStyle, enable, libBase);
  2636.  
  2637.     return(resultingStyle);
  2638. }
  2639.  
  2640. /* Logic behind AvailFonts() patch:
  2641.    textAttrs use pointers to names, not the names themselves.  So the names
  2642.    need to be in that memory space somewhere.  I work around diskfont.library's
  2643.    AvailFonts() call by spotting the temporary AvailFontsHeader in the middle
  2644.    of the memory pool, then call it with the original parameters, and copy
  2645.    the NumEntries value.  Then I add my extra data at the end of where 
  2646.    diskfont.library put its extra data, and fill in the beginning of the pool
  2647.    with my (T)AvailFonts, NumEntries plus numTAs, then exit. (whew.) */
  2648. __geta4 __regargs LONG NewAvailFonts(__A0 struct AvailFontsHeader *afhBuffer, __D0 LONG afBufSize, __D1 ULONG afFlags, __A6 struct Library *libBase)
  2649. {
  2650.     /* Use local ptrs */
  2651. struct    ATEAvailFonts        *nafAteAvailFonts;
  2652. struct    SignalSemaphore        *nafSemaphore = &aafSemaphore;
  2653. struct    AvailFonts        *nafAvailFonts;
  2654. struct    TAvailFonts        *nafTAvailFonts;
  2655.     int            diskAFSize, ateAFSize, ramAFSize, ateDataSize;
  2656.     int            totalAFSize, tempAFSize;
  2657.     int            numAteAfs, numEachName;
  2658.     int            numAmigaAfs, index, index2;
  2659. struct    AvailFontsHeader    *tempAfhBuffer;
  2660.     char            *ateFontNames;
  2661. struct    TagItem            *ateTags;
  2662.  
  2663.     /* First get access to the ATEAvailFonts struct */
  2664.     ObtainSemaphoreShared(nafSemaphore);
  2665.  
  2666.     /* Preload local variables */
  2667.     nafAteAvailFonts = ateAvailFonts;
  2668.     diskAFSize = nafAteAvailFonts->aaf_SizeDiskFonts;
  2669.     ateAFSize = nafAteAvailFonts->aaf_SizeATEFonts;
  2670.     ateDataSize = nafAteAvailFonts->aaf_SizeATEData;
  2671.     numEachName = nafAteAvailFonts->aaf_SizeMax / nafAteAvailFonts->aaf_SizeInc;
  2672.     numAteAfs = numEachName * nafAteAvailFonts->aaf_NumNames;
  2673.  
  2674.     /* Determine total size needed */
  2675.     ramAFSize = OldAvailFonts(afhBuffer, 0, afFlags & !(AFF_DISK), libBase);
  2676.     totalAFSize = ramAFSize;
  2677.     if (afFlags & AFF_DISK)
  2678.         totalAFSize = totalAFSize + diskAFSize + ateAFSize + ateDataSize;
  2679.     if (totalAFSize > afBufSize)
  2680.     {
  2681.         /* Reject and return space needed */
  2682.         ReleaseSemaphore(nafSemaphore);
  2683.         return(totalAFSize - afBufSize);
  2684.     }
  2685.  
  2686.     /* If they don't want diskfonts, call AvailFonts again and exit now */
  2687.     if (!(afFlags & AFF_DISK))
  2688.     {
  2689.         tempAFSize = OldAvailFonts(afhBuffer, afBufSize, afFlags, libBase);
  2690.         ReleaseSemaphore(nafSemaphore);
  2691.         return(tempAFSize);
  2692.     }
  2693.  
  2694.     /* Supposely we have enough space now.  Spot the beginning of the Amiga
  2695.        font list further down the list, by NumTAs * sizeof(struct [T]TextAttr) */
  2696.     if (afFlags & AFF_TAGGED)
  2697.         ateAFSize = sizeof(struct TAvailFonts) * numAteAfs;
  2698.     else
  2699.         ateAFSize = sizeof(struct AvailFonts) * numAteAfs;
  2700.     tempAfhBuffer = (struct AvailFontsHeader *)((ULONG)afhBuffer + ateAFSize);
  2701.  
  2702.     /* Call AvailFonts() with new buffer position */
  2703.     if (diskAFSize != 0)
  2704.         tempAFSize = OldAvailFonts(tempAfhBuffer, ramAFSize + diskAFSize, afFlags, libBase);
  2705.     else
  2706.         tempAFSize = OldAvailFonts(tempAfhBuffer, ramAFSize, (afFlags & (!AFF_DISK)), libBase);
  2707.  
  2708.     /* Position other pointers past Amiga availfonts data */
  2709.     ateTags = (struct TagItem *)((ULONG)afhBuffer + ateAFSize + ramAFSize + diskAFSize);
  2710.     ateFontNames = (char *)((ULONG)afhBuffer + ateAFSize + ramAFSize + diskAFSize + sizeof(struct TagItem) * 2);
  2711.     /* Insert tagitems and font names after Amiga availfonts data */
  2712.     ateTags[0].ti_Tag = nafAteAvailFonts->aaf_ATETags[0].ti_Tag;
  2713.     ateTags[0].ti_Data = nafAteAvailFonts->aaf_ATETags[0].ti_Data;
  2714.     ateTags[1].ti_Tag = nafAteAvailFonts->aaf_ATETags[1].ti_Tag;
  2715.     ateTags[1].ti_Data = nafAteAvailFonts->aaf_ATETags[1].ti_Data;
  2716.     /* Insert font names after the tagitems */
  2717.     for (index = 0; index < nafAteAvailFonts->aaf_NumNames; index++)
  2718.     {
  2719.         strcpy(&ateFontNames[index * 32], &nafAteAvailFonts->aaf_FontNames[index * 32]);
  2720.     }
  2721.     /* Get number of Non-ATE AFs */
  2722.     numAmigaAfs = tempAfhBuffer->afh_NumEntries;
  2723.  
  2724.     /* Now insert ATE TextAttrs at the top of the list */
  2725.     afhBuffer->afh_NumEntries = numAmigaAfs + numAteAfs;
  2726.     /* Do two versions: one for AvailFonts and one for TAvailFonts */
  2727.     if (afFlags & AFF_TAGGED)
  2728.     {
  2729.         nafTAvailFonts = (struct TAvailFonts *)&afhBuffer[1];
  2730.         for (index = 0; index < nafAteAvailFonts->aaf_NumNames; index++)
  2731.         {
  2732.             for (index2 = 1; index2 <= numEachName; index2++)
  2733.             { 
  2734.                 nafTAvailFonts->taf_Type = AFF_DISK;
  2735.                 nafTAvailFonts->taf_Attr.tta_Name = &ateFontNames[index * 32];
  2736.                 nafTAvailFonts->taf_Attr.tta_YSize = nafAteAvailFonts->aaf_SizeInc * index2;
  2737.                 nafTAvailFonts->taf_Attr.tta_Style = FS_NORMAL | FSF_TAGGED;
  2738.                 nafTAvailFonts->taf_Attr.tta_Flags = FPF_DESIGNED | FPF_DISKFONT | FPF_PROPORTIONAL;
  2739.                 nafTAvailFonts->taf_Attr.tta_Tags = ateTags;
  2740.                 nafTAvailFonts++;
  2741.             }
  2742.         }
  2743.     }
  2744.     else
  2745.     {
  2746.         nafAvailFonts = (struct AvailFonts *)&afhBuffer[1];
  2747.         for (index = 0; index < nafAteAvailFonts->aaf_NumNames; index++)
  2748.         {
  2749.             for (index2 = 1; index2 <= numEachName; index2++)
  2750.             {
  2751.                 nafAvailFonts->af_Type = AFF_DISK;
  2752.                 nafAvailFonts->af_Attr.ta_Name = &ateFontNames[index * 32];
  2753.                 nafAvailFonts->af_Attr.ta_YSize = nafAteAvailFonts->aaf_SizeInc * index2;
  2754.                 nafAvailFonts->af_Attr.ta_Style = FS_NORMAL;
  2755.                 nafAvailFonts->af_Attr.ta_Flags = FPF_DESIGNED | FPF_DISKFONT | FPF_PROPORTIONAL;
  2756.                 nafAvailFonts++;
  2757.             }
  2758.         }
  2759.     }
  2760.  
  2761.     ReleaseSemaphore(nafSemaphore);
  2762.     return(0);
  2763.     /* whew! */
  2764. }
  2765.  
  2766. /* Message sender.  This guy gets a lot of working out! */
  2767. BOOL ATESendMsg(struct ATEMessage *ateMsg)
  2768. {
  2769. struct    MsgPort        *msgPort, *replyPort;
  2770. struct    Message        *replyMsg;
  2771.     ULONG        portSig;
  2772.  
  2773. /* generate reply port */
  2774.     replyPort = CreateMsgPort();
  2775.     if (replyPort == 0)
  2776.         return(FALSE);
  2777.     
  2778. /* Reply port set up.  Now build the message. */
  2779.     ateMsg->ate_Message.mn_Length = ateMsg->ate_MsgLength;
  2780.     ateMsg->ate_Message.mn_ReplyPort = replyPort;
  2781.  
  2782. /* OK we have a valid reply port and a message.  Time to send it. */
  2783.     portSig = 1 << replyPort->mp_SigBit;
  2784.     msgPort = ateMsg->ate_DestPort;
  2785.     PutMsg(msgPort,(struct Message *)ateMsg);
  2786.     Wait(portSig);
  2787.     replyMsg=GetMsg(replyPort);
  2788.  
  2789. /* So, sent the message.  Now free the port & exit */
  2790.     DeleteMsgPort(replyPort);
  2791.     if ((msgPort != 0) && (replyMsg != 0))
  2792.         return(TRUE);
  2793.     else
  2794.         return(FALSE);
  2795. }
  2796.  
  2797. /* This function will provide a new font ptr in case the app calling
  2798.    a Text or text measuring function blatantly used a software style
  2799.    instead of asking for a style in OpenFont().  It also returns
  2800.    a fontnode for the Text() patch. 
  2801.  
  2802. struct FontNode *SwapSoftStyle(struct RastPort *rastPort, BOOL textSizer)
  2803. {
  2804. struct    List        *fontList = &ateFontList->fontList;
  2805. struct    SignalSemaphore    *ateSemaphore = &ateFontList->ateSemaphore;
  2806. struct    FontNode    *fontNode;
  2807.     char        searchString[64];
  2808.     int        checkATEvar;
  2809.     BOOL        softStyleMode = FALSE;
  2810.     BOOL        localOptSoftStyles = optSoftStyles;
  2811.     UBYTE        ateStyle = FS_NORMAL;
  2812.     UBYTE        ssModeOldStyle = rastPort->AlgoStyle;
  2813. struct    TextFont    *ssModeOldFont = rastPort->Font;
  2814.  
  2815.      First check for blatant software styles 
  2816.     ateStyle = ssModeOldStyle & (FSF_BOLD | FSF_ITALIC);
  2817.     checkATEvar = memcmp(rastPort->Font->tf_Message.mn_Node.ln_Name, "_ATE_", 5);
  2818.  
  2819.     if (ateStyle != FS_NORMAL && ckeckATEvar == 0)
  2820.         softStyleMode = TRUE;
  2821.     else
  2822.         return(0);
  2823.  
  2824.     if (softStyleMode == TRUE)
  2825.         sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, ateStyle);
  2826.     else
  2827.         sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, rastPort->Font->tf_Style);
  2828.  
  2829.     ObtainSemaphoreShared(ateSemaphore);
  2830.     fontNode = (struct FontNode *)FindName(fontList, searchString);
  2831.     ReleaseSemaphore(ateSemaphore);
  2832.     if (softStyleMode == TRUE && fontNode != 0)
  2833.     {
  2834.         if (fontNode->fn_BlackList == FALSE)
  2835.         {
  2836.             SetFont(rastPort, fontNode->fn_TextFont);
  2837.             OldSSStyle(rastPort, ssModeOldStyle ^ ateStyle,
  2838.                    FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED, gfxBase);
  2839.         }
  2840.         else
  2841.             fontNode = 0;
  2842.     }
  2843.     if (fontNode == 0)
  2844.     {
  2845.          Repeat search for normal style 
  2846.         sprintf(searchString, "%50s / %5d / %2x", rastPort->Font->tf_Message.mn_Node.ln_Name, rastPort->Font->tf_YSize, FS_NORMAL);
  2847.         ObtainSemaphoreShared(ateSemaphore);
  2848.         fontNode = (struct FontNode *)FindName(fontList, searchString);
  2849.         ReleaseSemaphore(ateSemaphore);
  2850.          If this was an ATE font without styles, cancel SoftStyle mode
  2851.  
  2852.         if (fontNode != 0)
  2853.         {
  2854.             softStyleMode = FALSE;
  2855.              If soft styles aren't allowed on ATE fonts, change it 
  2856.             if (localOptSoftStyles == FALSE)
  2857.                 OldSSStyle(rastPort, ssModeOldStyle ^ ateStyle,
  2858.                            FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED, gfxBase);
  2859.         }
  2860.     }
  2861.  
  2862.     return(fontNode);
  2863. }
  2864.  
  2865. void UndoSwapSoftStyle(struct RastPort *rastPort, struct TextFont *textFont, UBYTE softStyle)
  2866. {
  2867.  
  2868.     if (softStyle != 0)
  2869.     {
  2870.         SetFont(rastPort, textFont);
  2871.         OldSSStyle(rastPort, softStyle, FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED, gfxBase);
  2872.     }
  2873.  
  2874.     return;
  2875. } */
  2876.